LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 3190|回复: 11

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

[复制链接]
发表于 2008-10-4 23:48:58 | 显示全部楼层 |阅读模式
Makefile:2.6编译内核模块必用
virtual_char.c:内核模块源代码
test_virtual_char.c:测试源代码
 楼主| 发表于 2008-10-4 23:49:38 | 显示全部楼层
#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
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-10-4 23:50:34 | 显示全部楼层
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
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-10-4 23:51:02 | 显示全部楼层
//测试代码,用户空间
#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);               
    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;   
}
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-10-4 23:51:51 | 显示全部楼层
# 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
回复 支持 反对

使用道具 举报

发表于 2008-10-6 08:40:06 | 显示全部楼层

关于程序的一些疑问

1.请问在程序中诸如:printf("readbuf[%d]=%x\n",i,(unsigned char)readbuf); 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.还有我认为语句: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;
但是结果为什么会输出0,1,2,3呢?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-10-6 17:18:42 | 显示全部楼层
没啥关系,16进制看着清晰一些
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-10-6 17:20:15 | 显示全部楼层
ioctl调用和读写是两个,请看内核模块ioctl的实现
回复 支持 反对

使用道具 举报

发表于 2008-10-15 14:14:05 | 显示全部楼层
请问你这里的Makefile是内核代码中的Makefile还是自己写的makefile。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-10-20 11:04:22 | 显示全部楼层
Post by tempname;1894275
请问你这里的Makefile是内核代码中的Makefile还是自己写的makefile。


要自己写,这样很方便
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表