Linux---字符设备驱动程序设计

编写一个虚拟字符设备驱动程序char.c,

  1. 以内核模块的形式插入内核,编译方法与内核编译方法一致。
  2. 创建设备节点,然后通过编写一个测试程序,
  3. 功能:首先向设备中写入数据,再从设备中读出数据,并把数据显示在屏幕上。

4. 要求:设备名为:demo,主设务号为250,次设备号为0。

1、首先,要确保环境已经安装好了

Linux---字符设备驱动程序设计_第1张图片

开始写

写三个文件 

char.c 

Makefile    ps:M必须大写

test.c   用于测试

vi char.c
vi Makefile
vi test.c

这三个文件的具体代码我放在文末

写好了之后执行make命令

make

Linux---字符设备驱动程序设计_第2张图片

然后加载驱动程序

sudo insmod char.ko
lsmod //查看是否加载成功

必须使用管理员权限

Linux---字符设备驱动程序设计_第3张图片

在dev目录下创建设备文件

sudo mknod /dev/mychar c 250 0
//要使用管理员权限  
//1. 命令中的数字要和驱动程序定义的major,minor保持一致。
//2. Mychar文件名与测试程序 中的名字一致

编译运行测试程序

gcc test.c -o test
sudo ./test

Linux---字符设备驱动程序设计_第4张图片

 

char.c代码

#include    
#include
#include
#include
#include
#include
#include
#include

MODULE_LICENSE("GPL v2");   
MODULE_AUTHOR("Bob Geng");
MODULE_DESCRIPTION("a simple driver");

#define N    128

int major  = 250;
int minor  = 0;
struct cdev mycdev;    //字符型结构体

char buf[N] ={"hello world !!"};
int char_open (struct inode * myinode, struct file *fp)
{
    printk("char is opened\n");
    return 0;	
}
int char_release (struct inode *myinode, struct file *fp)
{
    printk("char is closeed\n");
    return 0;
}


static ssize_t char_read (struct file *filep, char __user *user_buf, size_t count, loff_t * off)
{  // 1. ssize_t :ssize_t是signed size_t;size_t: unsigned int
//2. Off:当前文件的偏移量
    ssize_t ret =0;
    long num =0;
    printk("char_read is called\n");
    printk("count is %d\n",count);
    num = copy_to_user(user_buf,buf,count);
    if(num < 0 )
    {
        printk("copy_to_user is failed\n");
        return ret;
    }
    return ret;
}

ssize_t char_write (struct file *filep, const char __user *from, size_t count, loff_t *off)
{
    ssize_t ret =0; 
    long num =0;
    printk("char_write is called \n");
    printk("count is %d\n",count);
 //   if(count > N )  return -ENOMEM;
    if(count > N )   count = N ;
    num = copy_from_user(buf,from,count);
    if(num < 0 )
    {
        printk("copy_to_user is failed\n");
        return ret;
    }
    printk("from  user is  %s\n",buf);
    return ret; 
}
struct file_operations fops={
    .owner = THIS_MODULE,
    .open  = char_open,
    .release = char_release,   
    .read  = char_read, 
    .write  = char_write, 
};
static int __init char_init(void)
{
    int ret;
    dev_t devno = MKDEV(major,minor);
    ret = register_chrdev_region(devno,1,"char");  //静态申请设备号
    if(ret < 0 )
    {
        printk("fail to get devno\n");
        return ret;
    }
    mycdev.owner = THIS_MODULE;
    cdev_init(&mycdev,&fops);
    ret = cdev_add(&mycdev,devno,1);
    if(ret < 0 )
    {
        printk("cdev_add fail to system\n");
        return ret;
    }
    printk("init_module\n");
    return 0;
}

static void __exit char_exit(void)
{

    dev_t devno = MKDEV(major,minor);
    cdev_del(&mycdev);
    unregister_chrdev_region(devno, 1);
    printk("cleanup_module\n");
}

module_init(char_init);
module_exit(char_exit);

Makefile代码

ifeq ($(KERNELRELEASE),)
KERNELDIR ?= /lib/modules/$(shell uname -r)/build  
#KERNELDIR ?= /home/linux/workdir/source-pack/linux-3.2-net/ (交叉编译)
M=$(PWD) modules
PWD := $(shell pwd)
modules:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

modules_install:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
clean:
	rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions Module* modules*
.PHONY: modules modules_install clean
else
obj-m :=char.o
endif

test.c代码

#include
#include
#include
#include 
#include 
#include 
#include 
#include 
#include 

#define   N   128
char buf[N] ; 
int main()
{
    int fd;
    if (  (fd = open("/dev/mychar",O_RDWR)) <  0)
    {
        perror("open");
        exit(-1);
    }

    if(read(fd,buf,N ) < 0 )
    {
        perror("read");
        exit(-1);
    }
    printf("read from mychar is %s\n",buf);
   // memset(buf,0,sizeof(buf));
    //strcpy(buf,"goddbye\0");
 printf("please input second buf:\n");
 scanf("%s",buf);
    if(write(fd,buf,N+1) < 0)
    {
        perror("write");
        exit(-1);
    }

    if(read(fd,buf,N ) < 0 )
    {
        perror("read");
        exit(-1);
    }
 printf("second read from mychar is %s\n",buf);
 getchar();
    printf("mychar is opened\n");
    close(fd);
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(Linux)