学习Linux内核小记 第3页(2)

下面一个文件是对 如何编写Linux设备驱动程序)()()中提到的例子的一些注释,方便理解这个例子。也可以说是一个整合。

test.c:

#define __NO_VERSION__
#include <linux/modules.h>
#include <linux/version.h>

#include <linux/types.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <asm/segment.h>
unsigned int test_major = 0;  //全局变量,主设备号

static int read_test(struct inode *node,struct file *file,char *buf,int count) //这个函数是为read调用准备的.当调用read时,read_test()被调用,它把用户的缓冲区全部写1
{

int left;
 
 if (verify_area(VERIFY_WRITE,buf,count) == -EFAULT ) //验证buf是否可用
  return -EFAULT;
 
 for(left = count ; left > 0 ; left--)
 {
  __put_user(1,buf,1);  //用于向用户传送数据,这是kernel提供的一个函数
  buf++;    //指针后移
 }
 return count; //返回buf的大小
}

static int write_tibet(struct inode *inode,struct file *file,const char *buf,int count)
{
 return count;
}

static int open_tibet(struct inode *inode,struct file *file )
{
 MOD_INC_USE_COUNT;
 return 0;
}

static void release_tibet(struct inode *inode,struct file *file )
{
 MOD_DEC_USE_COUNT;
}

struct file_operations test_fops = {   //把系统调用和驱动程序关联起来。系统调用通过设备文件的主设备号找到相应的设备驱动程序,然后读取这个数据结构相应的函数指针,接着把控制权交给该函数
 NULL,
 read_test,
 write_test,
 NULL,
 NULL,
 NULL,
 NULL,
 open_test,
 release_test, NULL,
 NULL,
 NULL,NULL
};

int init_module(void)
{
 int result;
 
 result = register_chrdev(0, "test", &test_fops);  //向系统的字符设备表登记了一个字符设备,如果登记成功,返回设备的主设备号
 
 if (result < 0) {   //不成功,返回一个负值
  printk(KERN_INFO "test: can't get major number\n");
  return result;
 }
 
 if (test_major == 0) test_major = result;
 return 0;
}

void cleanup_module(void)
{
 unregister_chrdev(test_major, "test");  //把register_chrdev()中自动分配的字符设备号给注销掉
}

编译:

$ gcc -O2 -DMODULE -D__KERNEL__ -c test.c

得到文件test.o就是一个设备驱动程序

安装到系统:

$ insmod -f test.o

卸载:

$ rmmod test
创建设备文件:

$ mknod /dev/test c major minor

c 是指字符设备,major是主设备号,就是在/proc/devices里看到的。

用shell命令

$ cat /proc/devices | awk "}"

minor是从设备号,设置成0就可以了

现在可以通过设备文件来访问我们的驱动程序了。

测试文件:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

main()
{
 int testdev;
 int i;
 char buf[10];
 
 testdev = open("/dev/test",O_RDWR); //打开设备文件
 
 if ( testdev == -1 )
 {
  printf("Cann't open file \n");
  exit(0);
 }
 
 read(testdev,buf,10);   //调用系统调用read,把用户的缓冲区全部写1
 
 for (i = 0; i < 10;i++)
  printf("%d\n",buf[i]);
 
 close(testdev);  //关闭设备文件
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwpxgd.html