+ -
当前位置:首页 → 问答吧 → 【新手请看】Linux2.6内核模块和驱动程序框架

【新手请看】Linux2.6内核模块和驱动程序框架

时间:2008-10-05

来源:互联网

Makefile:2.6编译内核模块必用
virtual_char.c:内核模块源代码
test_virtual_char.c:测试源代码

作者: hanchao3c   发布时间: 2008-10-05

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

#include <linux/fs.h>

#include <asm/uaccess.h>
#include <asm/io.h>


#include <linux/delay.h>

#define VIRTUAL_CHAR_MAJOR 240
#define VIRTUAL_CHAR_DEVICE_NAME "VirtualCharDevice"



static int virtual_char_open(struct inode *inode, struct file *file)
{
printk(KERN_EMERG"+++++++++++++++++++++\n");
printk(KERN_EMERG"virtual_char:device open\n");
printk(KERN_EMERG"pid=%d,comm=%s\n",current->pid,current->comm);
printk("device <%d,%d>\n",MAJOR(inode->i_rdev),MINOR(inode->i_rdev));
(file->private_data) = (void *)0x76543210;
return 0;
}

static int virtual_char_close(struct inode *inode, struct file *file)
{
printk(KERN_EMERG"virtual_char:device close\n");
printk(KERN_EMERG"----------------------\n");
return 0;
}

static ssize_t virtual_char_read(struct file *file, char *buf, size_t count, loff_t *offset)
{
printk(KERN_EMERG"virtual_char:device read=%d\n",count);
if(count >= sizeof(unsigned int)){
if(copy_to_user((void __user *)buf,(void *)(&file->private_data),sizeof(unsigned int)))
return -EFAULT;
}
return count;
}

static ssize_t virtual_char_write(struct file *file, const char *buf, size_t count, loff_t *offset)
{
printk(KERN_EMERG"virtual_char:device write=%d\n",count);
return count;
}

static loff_t virtual_char_llseek(struct file *file,loff_t offset,int whence)
{
printk(KERN_EMERG"virtual_char:device llseek: offset=%x whence=%x\n",(unsigned int)offset,whence);
return 0;
}

static int virtual_char_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
char argk[4];
argk[0] = 0;
argk[1] = 1;
argk[2] = 2;
argk[3] = 3;
printk(KERN_EMERG"virtual_char:device ioctl=%x\n",cmd);
switch(cmd)
{
case 0:
printk(KERN_EMERG"ctl NO.0\n");
if(copy_from_user(argk,(void __user *)arg,4))
return -EFAULT;
printk("arg=%x,%x,%x,%x\n",argk[0],argk[1],argk[2],argk[3]);
break;
case 1:
printk(KERN_EMERG"ctl NO.1\n");
if(copy_to_user((void __user *)arg,argk,4))
return -EFAULT;
break;
default:
break;
}
return 0;
}


static struct file_operations virtual_char_fops = {
.llseek = virtual_char_llseek,
.read = virtual_char_read,
.write = virtual_char_write,
.ioctl = virtual_char_ioctl,
.open = virtual_char_open,
.release = virtual_char_close,
};

static int virtual_char_init(void)
{
int res;

printk(KERN_EMERG"virtual_char register\n");
res = register_chrdev(VIRTUAL_CHAR_MAJOR, VIRTUAL_CHAR_DEVICE_NAME, &virtual_char_fops);
if (res < 0) {
printk(KERN_EMERG"virtual_char register fails\n");
return res;
}
// set_current_state(TASK_INTERRUPTIBLE);
// schedule_timeout(4000);
// mdelay(4000);

return 0;
}

static void virtual_char_cleanup(void)
{
printk(KERN_EMERG"virtual_char unregister\n");
unregister_chrdev(VIRTUAL_CHAR_MAJOR, VIRTUAL_CHAR_DEVICE_NAME);

return;
}


module_init(virtual_char_init);
module_exit(virtual_char_cleanup);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("HanChao");

//gcc -O2 -D__KERNEL__ -DMODULE -I/usr/include/ -c virtual_char.c -o m.ko

作者: hanchao3c   发布时间: 2008-10-05

obj-m:=virtual_char.o
#KDIR:=/lib/modules/2.6.18.2-34-default/build
KDIR:=/usr/src/linux
PWD:=$(shell pwd)
default:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
rm -rf *.o *.mod.o *.ko *.mod.c .*.o.cmd .*.mo.o.cmd .*.ko.cmd .tmp_versions

作者: hanchao3c   发布时间: 2008-10-05

//测试代码,用户空间
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>

#define DEF_FILE_NAME "/dev/virtualchar"

int main(int argc,char* argv[])
{
int fd,size,i;
char readbuf[8];
char writebuf[8] = "writebuf";
char ioarg[4];

char* dev_file;
if(1 == argc){
dev_file = DEF_FILE_NAME;
}else{
dev_file = argv[1];
}
printf("<<<< testfile name=%s >>>>\n",dev_file);
printf("pid=%d ppid=%d\n",getpid(),getppid());

/* write */
printf("=====write test=====\n");
fd=open(dev_file,O_WRONLY);
size = write(fd,writebuf,sizeof(writebuf));
close(fd);
printf("write size=%d\n",size);


/* read */
printf("=====read test=====\n");
fd=open(dev_file,O_RDONLY);
size=read(fd,readbuf,sizeof(readbuf));
close(fd);
printf("read size=%d\n",size);
for(i=0;i<size;i++)
printf("readbuf[%d]=%x\n",i,(unsigned char)readbuf[i]);
close(fd);

/* ioctl */
printf("=====ioctl test=====\n");
fd=open(dev_file,O_RDWR);
ioarg[0] = 0xf0;
ioarg[1] = 0xf1;
ioarg[2] = 0xf2;
ioarg[3] = 0xf3;

printf("ioctl test 0\n");
ioctl(fd,0,ioarg);

printf("ioctl test 1\n");
ioctl(fd,1,ioarg);
printf("arg=%x,%x,%x,%x\n",ioarg[0],ioarg[1],ioarg[2],ioarg[3]);
close(fd);


return 0;
}

作者: hanchao3c   发布时间: 2008-10-05

# make

make -C /usr/src/linux M=/home/hanchao/module modules
make[1]: Entering directory `/usr/src/linux-2.6.18.2-34'


CC [M] /home/hanchao/module/virtual_char.o

Building modules, stage 2.

MODPOST
CC /home/hanchao/module/virtual_char.mod.o
LD [M] /home/hanchao/module/virtual_char.ko
make[1]: Leaving directory `/usr/src/linux-2.6.18.2-34'


# mknod /dev/VirtualCharDevice c 240 0

# ls /dev/VirtualCharDevice -l
crw-r--r-- 1 root root 240, 0 04-25 06:46 /dev/VirtualCharDevice

# insmod virtual_char.ko



# ./test /dev/VirtualCharDevice
<<<< testfile name:/dev/VirtualCharDevice >>>>
pid:4671 ppid:4108
=====write test=====
write size:8
=====read test=====
read size:8
readbuf[0]:10
readbuf[1]:32
readbuf[2]:54
readbuf[3]:76
readbuf[4]:c9
readbuf[5]:87
readbuf[6]:4
readbuf[7]:8
=====ioctl test=====
ioctl test 0
ioctl test 1
arg:0,1,2,3

作者: hanchao3c   发布时间: 2008-10-05

1.请问在程序中诸如rintf("readbuf[%d]=%x\n",i,(unsigned char)readbuf[i]); printf("arg=%x,%x,%x,%x\n",ioarg[0],ioarg[1],ioarg[2],ioarg[3]);ioarg[0] = 0xf0;
ioarg[1] = 0xf1;
ioarg[2] = 0xf2;
ioarg[3] = 0xf3;
等语句为什么要用16进制来输出呢,是必须要这样做吗?
2.还有我认为语句rintf("arg=%x,%x,%x,%x\n",ioarg[0],ioarg[1],ioarg[2],ioarg[3]);应该输出的是ioarg[0] = 0xf0;
ioarg[1] = 0xf1;
ioarg[2] = 0xf2;
ioarg[3] = 0xf3;
但是结果为什么会输出0,1,2,3呢?

作者: txf1949   发布时间: 2008-10-06

没啥关系,16进制看着清晰一些

作者: hanchao3c   发布时间: 2008-10-06

ioctl调用和读写是两个,请看内核模块ioctl的实现

作者: hanchao3c   发布时间: 2008-10-06

请问你这里的Makefile是内核代码中的Makefile还是自己写的makefile。

作者: tempname   发布时间: 2008-10-15

引用:
作者: tempname
请问你这里的Makefile是内核代码中的Makefile还是自己写的makefile。
要自己写,这样很方便

作者: hanchao3c   发布时间: 2008-10-20

LZ能将 为什么要 include 那几个文件 讲一下吗? 呵呵

作者: goldenfire   发布时间: 2008-11-14

好帖子,正在研究呢。

作者: neubuffalo   发布时间: 2008-11-15