博客首页 注册 建议与交流 排行榜 加入友情链接
推荐 投诉 搜索: 帮助

“开源一刻”工作室

    欢迎光临“开源一刻”。本站点主要从事开源资料的的收集汇总等等,主要包括操作系
统、程序设计、桌面应用等等各个方面的信息,希望各位多多光临指教,互相交流。本站资
源均来自互联网,如果本站收集的内容侵犯了您的版权,请及时通知本人,本人将在第一时
间内删除。
    本人经营各类linux、BSD、Solaris等各类开源操作系统,欢迎光临本人网店。
     [开源一刻]工作室——淘宝网店
    
   icyworld.cublog.cn
关于作者  
姓名:飞飞侠
职业:嵌入式软件开发工程师
年龄:26
位置:广东广州
个性介绍:稳重,大方

我的分类  




深入浅出 Linux字符设备驱动程序解析(2)

llseek()函数 该函数用来修改文件的当前读写位置,并将新位置作为(正的)返回值返回,原型为:

loff_t (*llseek) (struct file *, loff_t, int);

poll()函数 poll 方法是poll 和select 这两个系统调用的后端实现,用来查询设备是否可读或可写,或是否处于某种特殊状态,原型为:

unsigned int (*poll) (struct file *, struct poll_table_struct *);

我们将在"设备的阻塞与非阻塞操作"一节对该函数进行更深入的介绍。

 设备"gobalvar"的驱动程序的这些函数应分别命名为gobalvar_open、 gobalvar_ release、gobalvar_read、gobalvar_write、gobalvar_ioctl,因此设备"gobalvar"的基本入口点结构变量gobalvar_fops 赋值如下:

struct file_operations gobalvar_fops = {

 read: gobalvar_read,

 write: gobalvar_write,

};

  上述代码中对gobalvar_fops的初始化方法并不是标准C所支持的,属于GNU扩展语法

  完整的globalvar.c文件源代码如下:

#include <linux/module.h>

#include <linux/init.h>

#include <linux/fs.h>

#include <asm/uaccess.h> 

MODULE_LICENSE("GPL");

#define MAJOR_NUM 254 //主设备号

static ssize_t globalvar_read(struct file *, char *, size_t, loff_t*);

static ssize_t globalvar_write(struct file *, const char *, size_t, loff_t*);

//初始化字符设备驱动的file_operations结构体

struct file_operations globalvar_fops =

{

 read: globalvar_read, write: globalvar_write,

};

static int global_var = 0; //"globalvar"设备的全局变量

static int __init globalvar_init(void)

{

 int ret;

 //注册设备驱动

 ret = register_chrdev(MAJOR_NUM, "globalvar", &globalvar_fops);

 if (ret)

 {

  printk("globalvar register failure");

 }

 else

 {

  printk("globalvar register success");

 }

 return ret;

}

static void __exit globalvar_exit(void)

{

 int ret;

 //注销设备驱动

 ret = unregister_chrdev(MAJOR_NUM, "globalvar");

 if (ret)

 {

  printk("globalvar unregister failure");

 }

 else

 {

  printk("globalvar unregister success");

 }

}

static ssize_t globalvar_read(struct file *filp, char *buf, size_t len, loff_t *off)

{

 //将global_var从内核空间复制到用户空间

 if (copy_to_user(buf, &global_var, sizeof(int)))

 {

  return - EFAULT;

 } 

 return sizeof(int);

}

static ssize_t globalvar_write(struct file *filp, const char *buf, size_t len, loff_t *off)

{

 //将用户空间的数据复制到内核空间的global_var

 if (copy_from_user(&global_var, buf, sizeof(int)))

 {

  return - EFAULT;

 } 

 return sizeof(int);

}

module_init(globalvar_init);

module_exit(globalvar_exit); 

  运行:

gcc -D__KERNEL__ -DMODULE -DLINUX -I /usr/local/src/linux2.4/include -c -o globalvar.o globalvar.c 

  编译代码,运行:

inmod globalvar.o 

  加载globalvar模块,再运行:

cat /proc/devices 

  发现其中多出了"254 globalvar"一行,如下图:

 

  接着我们可以运行:

mknod /dev/globalvar c 254 0 

  创建设备节点,用户进程通过/dev/globalvar这个路径就可以访问到这个全局变量虚拟设备了。

我们写一个用户态的程序globalvartest.c来验证上述设备:

#include <sys/types.h>

#include <sys/stat.h>

#include <stdio.h>

#include <fcntl.h>

main()

{

 int fd, num;

 //打开"/dev/globalvar"

 fd = open("/dev/globalvar", O_RDWR, S_IRUSR | S_IWUSR);

 if (fd != -1 )

 {

  //初次读globalvar

  read(fd, &num, sizeof(int));

  printf("The globalvar is %d\n", num);

  //写globalvar

  printf("Please input the num written to globalvar\n");

  scanf("%d", &num);

  write(fd, &num, sizeof(int));

  //再次读globalvar

  read(fd, &num, sizeof(int));

  printf("The globalvar is %d\n", num);

  //关闭"/dev/globalvar"

  close(fd);

 }

 else

 {

  printf("Device open failure\n");

 }

} 

  编译上述文件:

gcc -o globalvartest.o globalvartest.c 

  运行

./globalvartest.o 

  可以发现"globalvar"设备可以正确的读写。

 原文地址 http://www.qqread.com/linux/2007/04/t311030_2.html
 发表于: 2007-08-30,修改于: 2007-08-30 17:17 已浏览630次,有评论0条 推荐 投诉

  网友评论

  发表评论



Copyright © 2001-2010 ChinaUnix.net All Rights Reserved

感谢所有关心和支持过ChinaUnix的朋友们
页面生成时间:0.0179

京ICP证041476号