如何编写Linux的驱动程序

 我来答
城南明月羿当年
2015-05-13 · 知道合伙人生活技巧行家
城南明月羿当年
知道合伙人生活技巧行家
采纳数:24666 获赞数:123228
计算机爱好者

向TA提问 私信TA
展开全部
};  //IO功能选项,硬件上拉输出  static unsigned int gpio_cfg_table[] = {      S3C2410_GPB5_OUTP,    S3C2410_GPB6_OUTP,    S3C2410_GPB7_OUTP,    S3C2410_GPB8_OUTP, };  //编写一个ioctl函数,这个函数提供给用户端使用(也就是用户态使用)  static int my_ioctl(struct inode *inode,struct file* file,unsigned int cmd,           unsigned long arg) {                 if (arg > 4)        {            return -EINVAL;        }         if (cmd == 1) //led ON        {             s3c2410_gpio_setpin(gpio_table[arg],0);            return 0;        }         if (cmd == 0) //led OFF        {            s3c2410_gpio_setpin(gpio_table[arg],1);           return 0;        }        else        {             return -EINVAL;        }  }  //一个和文件设备相关的结构体。  static struct file_operations dev_fops =  {         .owner = THIS_MODULE,        .ioctl = my_ioctl,         //.read  = my_read,   //这个暂时屏蔽,一会我们再加入一个读操作的函数 };  //linux中设备的注册结构体 static struct miscdevice misc = 
{         .minor = MISC_DYNAMIC_MINOR,        .name  = DEVICE_NAME,        .fops  = &dev_fops, };  //设备初始化(包括注册)函数 static int __init dev_init(void) {         int ret;        int i;         for (i=0;i<4;i++)        {             s3c2410_gpio_cfgpin(gpio_table[i],gpio_cfg_table[i]);            s3c2410_gpio_setpin(gpio_table[i],0);            mdelay(500);             s3c2410_gpio_setpin(gpio_table[i],1);        }         ret = misc_register(&misc);         printk(DEVICE_NAME"MY_LED_DRIVER init ok\n");        return ret; }  //设备注销函数   static void __exit dev_exit(void) {         misc_deregister(&misc); }  //与模块相关的函数 module_init(dev_init); module_exit(dev_exit); MODULE_LICENSE("GPL");  MODULE_AUTHOR("blog.ednchina.com/itspy"); 
MODULE_DESCRIPTION("MY LED DRIVER");  到此,上面就完成了一个简单的驱动(别急,下面我们再会稍微增加点复杂的东西),以上代码的可以简单概括为:像自己写51单片机或者ARM的裸奔程序一样操作IO函数,然后再linux系统中进行相关必须的函数关联和注册。 为什么要关联呢,为什么注册呢? 因为这是必须的,从以下这些结构体就知道了。 stuct file_operations{  struct module *owner;  loff_t (*llseek) (struct file *, loff_t, int);  ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);  ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);  ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);  ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);  int (*readdir) (struct file *, void *, filldir_t); 
 unsigned int (*poll) (struct file *, struct poll_table_struct *);  int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);  long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); … }  file_operations 结构体中包括了很多与设备相关的函数指针,指向了驱动所提供的函数。 struct inode{  struct hlist_node i_hash;  struct list_head i_list;  struct list_head i_sb_list;  struct list_head i_dentry;  unsigned long  i_ino;  atomic_t  i_count;  unsigned int  i_nlink;  uid_t   i_uid;  gid_t   i_gid;  dev_t   i_rdev;  u64   i_version;  loff_t   i_size; … }     inode 是 UNIX 操作系统中的一种数据结构,它包含了与文件系统中各个文件相关的一些重要信息。在 UNIX 中创建文件系统时,同时将会创建大量的 inode 。通常,文件系统磁盘空间中大约百分之一空间分配给了 inode 表。  大略了解以上信息之后,我们只需把我们所要实现的功能和结构体关联起来。上例中已经完成IO写操作的函数,现在我们再添加一个读的函数。基于这种原理,我们想实现各种功能的驱动也就很简单了。  //添加读函数示意, 用户层可以通过 read函数来操作。  static int my_read(struct file* fp, char __user *dat,size_t cnt) {        size_t i;         printk("now read the hardware...\n");       for(i=0;i<cnt;i++)           dat[i] = 'A';       dat[i] = '\0';       return cnt;  }  这样,完成驱动编写。编译之后,本驱动可以通过直接嵌入内核中,也可以以模块的嵌入的形式加载到linux内核中去。  完成了驱动,写个应用程序了验证一下吧:  int main(int argc,char ** argv) {  
    int on;     int led_no;     int fd;     char str[10];     int cnt =0;      fd = open("/dev/MY_LED_DRIVER",0);     if (fd < 0)     {         printf("can't open dev\n");        exit(1);         }      printf("read process\n");     cnt = read(fd,str,10);      printf("get data from driver:\n%s\ncount = %d\n",str,cnt);     printf("read process end \n");     cnt = 0;      printf("running...\n");     while(cnt++<1000)     {        ioctl(fd,0,0);  //led off        ioctl(fd,0,1);       ioctl(fd,0,2);       ioctl(fd,0,3);       sleep(1);   //printf("sdfdsfdsfdsfds...\n");       ioctl(fd,1,0);  //led on       ioctl(fd,1,1);       ioctl(fd,1,2);       ioctl(fd,1,3);       sleep(1);        printf("%d\b",cnt);     }      close(fd);     return 0; }
名片
2024-10-28 广告
Altair HyperWorks是一套功能强大的集成化CAE(计算机辅助工程)软件平台,由Altair公司开发。它涵盖了结构分析、流体动力学、优化、多体动力学、电磁场仿真等多个领域,提供了丰富的仿真工具和优化算法。HyperWorks以其... 点击进入详情页
本回答由名片提供
chr1999
2015-05-08 · TA获得超过1056个赞
知道小有建树答主
回答量:2462
采纳率:0%
帮助的人:1240万
展开全部
看本书ldd
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式