RSS
热门关键字:  几款非主流QQ头像  数字的颜色  峡谷攻防战  依然非主流QQ头像  QQ卡通可爱头像

Linux下的C编程实战之5

来源: 作者: 时间:2008-03-29 点击:

关键字:Linux下的C编程实战之五 实战宝典:如何双引导Vista和Linux 硬盘等存储设备另类安装方案 USB设备还能这样安装 音频设备无的解决方法 另类玩法 USB设备还能这样安装 Cisco和H3C交换设备 ARP病毒快速解决办法 int

1.引言

  设备驱动程序操作系统内核和机器硬件之间接口它为应用程序屏蔽硬件细节一般来说Linux设备驱动程序需要完成如下功能:

  (1)初始化设备;

  (2)提供各类设备服务;

  (3)负责内核和设备之间数据交换;

  (4)检测和处理设备工作过程中出现错误

  妙不可言Linux下设备驱动程序被组织为一组完成不同任务函数集合通过这些函数使得Windows设备操作犹如文件一般在应用程序看来硬件设备只一个设备文件应用程序可以象操作普通文件一样对硬件设备进行操作本系列文章第2章文件系统编程中已经看到这些函数真面目它们就open ()、close ()、read ()、write () 等
小编推荐:

天地广owide.com




  Linux主要将设备分为二类:字符设备和块设备(当然网络设备及USB等其它设备驱动编写方法又稍有不同)这两类设备不同点在于:在对字符设备发出读/写请求时实际硬件I/O一般就紧接着发生而块设备则不然它利用一块系统内存作缓冲区当用户进程对设备请求能满足用户要求就返回请求数据如果不能就调用请求函数来进行实际I/O操作块设备主要针对磁盘等慢速设备以字符设备驱动较为简单因此本章主要阐述字符设备驱动编写 大学城uniuc.com

  2.驱动模块函数

  init 函数用来完成对所控设备初始化工作并调用register_chrdev() 函数注册字符设备假设有一字符设备“exampledev”则其init 函数为:

void exampledev_init(void)
{
 if (register_chrdev(MAJOR_NUM, " exampledev ", &exampledev_fops))
  TRACE_TXT("Device exampledev driver registered error");
 else
  TRACE_TXT("Device exampledev driver registered successfully");
  …//设备初始化
}

  其中register_chrdev函数中参数MAJOR_NUM为主设备号,“exampledev”为设备名exampledev_fops为包含基本函数入口点结构体类型为file_operations当执行exampledev_init时它将调用内核函数register_chrdev把驱动程序基本入口点指针存放在内核字符设备地址表中在用户进程对该设备执行系统调用时提供入口地址
一流导航网16dh.com


  file_operations结构体定义为:

struct file_operations
{
 int (*lseek)();
 int (*read)();
 int (*write)();
 int (*readdir)();
 int (*select)();
 int (*ioctl)();
 int (*mmap)();
 int (*open)();
 void(*release)();
 int (*fsync)();
 int (*fasync)();
 int (*check_media_change)();
 void(*revalidate)();
};

  大多数驱动程序只利用其中一部分对于驱动程序中无需提供功能只需要把相应位置值设为NULL对于字符设备来说要提供主要入口有:open ()、release ()、read ()、write ()、ioctl ()

无忧词典51dic.com



  open()函数 对设备特殊文件进行open()系统调用时将调用驱动程序open () 函数:

int open(struct inode * inode ,struct file * file);

  其中参数inode为设备特殊文件inode (索引结点) 结构指针参数file指向这一设备文件结构指针open()主要任务确定硬件处在就绪状态、验证次设备号合法性(次设备号可以用MINOR(inode-> i - rdev) 取得)、控制使用设备进程数、根据执行情况返回状态码(0表示成功负数表示存在错误) 等;

  release()函数 当最后一个打开设备用户进程执行close ()系统调用时内核将调用驱动程序release () 函数:
行业搜hysoo.com


void release (struct inode * inode ,struct file * file) ;

  release 函数主要任务清理未结束输入/输出操作、释放资源、用户自定义排他标志复位等
read()函数 当对设备特殊文件进行read() 系统调用时将调用驱动程序read() 函数:

void read(struct inode * inode ,struct file * file ,char * buf ,int count) ;

  参数buf指向用户空间缓冲区指针由用户进程给出count 为用户进程要求读取字节数也由用户给出
天地广owide.com


  read() 函数功能就从硬设备或内核内存中读取或复制count个字节到buf 指定缓冲区中在复制数据时要注意驱动程序运行在内核中而buf指定缓冲区在用户内存区中不能直接在内核中访问使用因此必须使用特殊复制函数来完成复制工作这些函数在<asm/ segment.h>中定义:

void put_user_byte (char data_byte ,char * u_addr) ;
void put_user_word (short data_word ,short * u_addr) ;
void put_user_long(long data_long ,long * u_addr) ;
void memcpy_tofs (void * u_addr ,void * k_addr ,unsigned long cnt) ;

大学城uniuc.com


  参数u_addr为用户空间地址k_addr 为内核空间地址cnt为字节数

  write( ) 函数 当设备特殊文件进行write () 系统调用时将调用驱动程序write () 函数:

void write (struct inode * inode ,struct file * file ,char * buf ,int count) ;

  write ()功能将参数buf 指定缓冲区中count 个字节内容复制到硬件或内核内存中和read() 一样复制工作也需要由特殊函数来完成:

unsigned char_get_user_byte (char * u_addr) ;
unsigned char_get_user_word (short * u_addr) ;
unsigned char_get_user_long(long * u_addr) ; 大学城uniuc.com
unsigned memcpy_fromfs(void * k_addr ,void * u_addr ,unsigned long cnt) ;

  ioctl() 函数 该函数特殊控制函数可以通过它向设备传递控制信息或从设备取得状态信息函数原型为:

int ioctl (struct inode * inode ,struct file * file ,unsigned int cmd ,unsigned long arg);

  参数cmd为设备驱动程序要执行命令代码由用户自定义参数arg 为相应命令提供参数类型可以整型、指针等

  同样在驱动程序中这些函数定义也必须符合命名规则按照本文约定设备“exampledev”驱动程序这些函数应分别命名为exampledev_open、exampledev_ release、exampledev_read、exampledev_write、exampledev_ioctl因此设备“exampledev”基本入口点结构变量exampledev_fops 赋值如下:

天地广owide.com



struct file_operations exampledev_fops {
 NULL ,
 exampledev_read ,
 exampledev_write ,
 NULL ,
 NULL ,
 exampledev_ioctl ,
 NULL ,
 exampledev_open ,
 exampledev_release ,
 NULL ,
 NULL ,
 NULL ,
 NULL
} ;
上一篇:Linux操作系统下修改IP、DNS等网络配置
下一篇:没有了
最新评论共有 0 位网友发表了评论
发表评论
评论内容:不能超过250字,需审核,请自觉遵守互联网相关政策法规。
用户名: 密码:
匿名?
注册
栏目列表