[블로그 통합으로 이전해 온 자료] - 2008. 4. 24. 02:24
%% LDD 3판에서 따옴
loaddev - 드라이버를 로드하고 nod 파일을 만든다.
#!/bin/sh
MODULE="template"
DEVICE="template"
MODE="664"
if grep -q '^staff:' /etc/group; then
GROUP="staff"
else
GROUP="wheel"
fi
/sbin/insmod $MODULE.ko $* || exit 1
MAJOR=$(awk "\$2==\"$MODULE\" " /proc/devices)
rm -rf /dev/$[0-3]
mknod /dev/$0 c $MAJOR 0
mknod /dev/$1 c $MAJOR 0
mknod /dev/$2 c $MAJOR 0
mknod /dev/$3 c $MAJOR 0
ln -sf $0 /dev/$
chgrp $GROUP /dev/$[0-3]
chmod $MODE /dev/$[0-3]
unloaddev - 드라이버 언로드
#!/bin/sh
MODULE="template"
DEVICE="template"
/sbin/rmmod $MODULE $* || exit
Makefile
ifneq ($(KERNELRELEASE),)
template-objs := main.o utils.o proc.o
obj-m := template.o
else
KERNELDIR ?= /opt/arm9sbc/ahav/kernel/linux-2.6.22.8
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions Module.symvers
template.h
#ifndef __TEMPLATE_H__
#define __TEMPLATE_H__
#include <linux/ioctl.h>
#define TEMPLATE_MAJOR 0
#define TEMPLATE_NR_DEVS 4
extern int template_major; // template_main.c
extern int template_nr_devs;
void template_create_proc( void );
void template_remove_proc( void );
#define TEMPLATE_IOC_MAGIC 'k'
#define TEMPLATE_IOCRESET _IO(TEMPLATE_IOC_MAGIC, 0)
#define TEMPLATE_IOCSQUANTUM _IOW(TEMPLATE_IOC_MAGIC, 1, int)
#define TEMPLATE_IOCSQSET _IOW(TEMPLATE_IOC_MAGIC, 2, int)
#define TEMPLATE_IOCTQUANTUM _IO(TEMPLATE_IOC_MAGIC, 3)
#define TEMPLATE_IOCTQSET _IO(TEMPLATE_IOC_MAGIC, 4)
#define TEMPLATE_IOCGQUANTUM _IOR(TEMPLATE_IOC_MAGIC, 5, int)
#define TEMPLATE_IOCGQSET _IOR(TEMPLATE_IOC_MAGIC, 6, int)
#define TEMPLATE_IOCQQUANTUM _IO(TEMPLATE_IOC_MAGIC, 7)
#define TEMPLATE_IOCQQSET _IO(TEMPLATE_IOC_MAGIC, 8)
#define TEMPLATE_IOCXQUANTUM _IOWR(TEMPLATE_IOC_MAGIC, 9, int)
#define TEMPLATE_IOCXQSET _IOWR(TEMPLATE_IOC_MAGIC, 10, int)
#define TEMPLATE_IOCHQUANTUM _IO(TEMPLATE_IOC_MAGIC, 11)
#define TEMPLATE_IOCHQSET _IO(TEMPLATE_IOC_MAGIC, 12)
#define TEMPLATE_P_IOCTSIZE _IO(TEMPLATE_MAGIC, 13)
#define TEMPLATE_P_IOCQSIZE _IO(TEMPLATE_MAGIC, 14)
#define TEMPLATE_IOC_MAXNR 14
#endif
main.c - module 의 메인
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/kernel.h> // printk()
#include <linux/slab.h> // kmalloc()
#include <linux/fs.h> //
#include <linux/errno.h> // error code
#include <linux/types.h> // size_t
#include <linux/proc_fs.h>
#include <linux/fcntl.h> // O_ACCMODE
#include <linux/cdev.h>
#include <asm/system.h> // cli(), *_flags
#include <asm/uaccess.h> // copy_*_user()
#include "template.h"
int template_major = TEMPLATE_MAJOR;
int template_minor = 0;
int template_nr_devs = 0;
char global_data[100];
module_param( template_major, int, S_IRUGO );
module_param( template_minor, int, S_IRUGO );
MODULE_AUTHOR( "Choi, Jae-woo" );
MODULE_LICENSE( "Dual BSD/GPL" );
int template_open( struct inode *inode, struct file *filp )
{
return 0;
}
int template_release( struct inode *inode, struct file *filp )
{
return 0;
}
ssize_t template_read( struct file *filp, char __user *buf, size_t count, loff_t *f_pos )
{
ssize_t retval = 0;
// down_interruptible();
// .....
if ( copy_from_user( global_data, buf, count ) )
{
retval = -EFAULT;
goto out;
}
*f_pos += count;
retval = count;
out:
// up();
return retval;
}
ssize_t template_write( struct file *filp, const char __user *buf, size_t count, loff_t *f_pos )
{
ssize_t retval = 0;
// down_interruptible();
// .....
if ( copy_from_user( global_data, buf, count ) )
{
retval = -EFAULT;
goto out;
}
*f_pos += count;
retval = count;
out:
// up( );
return retval;
}
int template_ioctl( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg )
{
int err = 0;
int retval = 0;
if ( _IOC_TYPE( cmd ) != TEMPLATE_IOC_MAGIC )
return -ENOTTY;
if ( _IOC_NR( cmd ) > TEMPLATE_IOC_MAXNR )
return -ENOTTY;
if ( _IOC_DIR( cmd ) & _IOC_READ )
err = ! access_ok( VERIFY_WRITE, (void __user *) arg, _IOC_SIZE( cmd ) );
else if ( _IOC_DIR( cmd ) & _IOC_WRITE )
err = ! access_ok( VERIFY_READ, (void __user *) arg, _IOC_SIZE( cmd ) );
if ( err )
return -EFAULT;
switch ( cmd )
{
case TEMPLATE_IOCRESET:
break;
default:
return -ENOTTY;
}
return retval;
}
loff_t template_llseek( struct file *filp, loff_t off, int whence )
{
loff_t newpos;
switch ( whence )
{
case 0 : // SEEK_SET
newpos = off;
break;
case 1 : // SEEK_CUR
newpos = filp->f_pos + off;
break;
case 2 : // SEEK_END
newpos = sizeof( global_data ) + off;
break;
default :
return -EINVAL;
}
if ( newpos < 0 )
return -EINVAL;
filp->f_pos = newpos;
return newpos;
}
struct file_operations template_fops =
{
.owner = THIS_MODULE,
.llseek = template_llseek,
.read = template_read,
.write = template_write,
.ioctl = template_ioctl,
.open = template_open,
.release = template_release,
};
static void template_cleanup_module( void )
{
dev_t devno = MKDEV( template_major, template_minor );
// template_remove_proc( );
unregister_chrdev_region( devno, template_nr_devs );
}
static int template_init_module( void )
{
int result;
dev_t dev = 0;
result = alloc_chrdev_region( &dev, template_minor, template_nr_devs, "template" );
template_major = MAJOR( dev );
if ( result < 0 )
{
printk( KERN_WARNING "template: can't get major %d\n", template_major );
return result;
}
dev = MKDEV( template_major, template_minor + template_nr_devs );
// template_create_proc( );
return 0;
}
module_init( template_init_module );
module_exit( template_cleanup_module );
proc.c - proc fs 관련
#include <linux/module.h>
#include <linux/kernel.h> // printk()
#include <linux/slab.h> // kmalloc()
#include <linux/fs.h> //
#include <linux/errno.h> // error code
#include <linux/types.h> // size_t
#include <linux/proc_fs.h>
// #include <linux/fcntl.h> // O_ACCMODE
#include <linux/seq_file.h>
#include <linux/cdev.h>
// #include <asm/system.h> // cli(), *_flags
// #include <asm/uaccess.h> // copy_*_user()
#include "template.h"
int template_read_procmem( char *buf, char **start, off_t offset, int count, int *eof, void *data )
{
int len = 0;
return len;
}
static void *template_seq_start( struct seq_file *s, loff_t *pos )
{
return (void *) NULL;
}
static void *template_seq_next( struct seq_file *s, void *v, loff_t *pos )
{
return (void *) NULL;
}
static void template_seq_stop( struct seq_file *s, void *v )
{
}
static int template_seq_show( struct seq_file *s, void *v )
{
return 0;
}
static struct seq_operations template_seq_ops =
{
.start = template_seq_start,
.next = template_seq_next,
.stop = template_seq_stop,
.show = template_seq_show
};
static int template_proc_open( struct inode *inode, struct file *file )
{
return seq_open( file, &template_seq_ops );
}
static struct file_operations template_proc_ops =
{
.owner = THIS_MODULE,
.open = template_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release
};
void template_create_proc( void )
{
struct proc_dir_entry *entry;
create_proc_read_entry( "templatemem", 0, NULL, template_read_procmem, NULL );
entry = create_proc_entry( "templateseq", 0, NULL );
if ( entry )
entry->proc_fops = &template_proc_ops;
}
void template_remove_proc( void )
{
remove_proc_entry( "templatemem", NULL );
remove_proc_entry( "templateseq", NULL );
}
utils.c - 기타 함수들
#include <linux/kernel.h> // printk()
#include <linux/slab.h> // kmalloc()
#include <linux/cdev.h>
#include "template.h"
'실습 > 리눅스 커널' 카테고리의 다른 글
커널 타이머, 태스크릿, 작업큐 (0) | 2021.02.08 |
---|---|
드라이버 코드의 실행 지연 (0) | 2021.02.08 |
커널에서 Blocking I/O (0) | 2021.02.08 |
커널에서 condition race 제거 (0) | 2021.02.08 |
Kernel Module 컴파일을 위한 Makefile 만들기 (0) | 2021.02.08 |