免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1204 | 回复: 0

linux 驱动HelloWorld [复制链接]

论坛徽章:
0
发表于 2008-09-15 07:18 |显示全部楼层
读Linux设备驱动第三版一书 练习笔记

思路:注册一个设备,当用户调用读取操作时返回给用户当前的进程列表

hello.c //源文件

#include       //指定初始化和清理函数Module init和Module exit宏        
#include     //moudle.h 包含了大量加载模块需要的函数和符号的定义
#include    //内核代码的 printk,输出优先级等内核代码
#include      //kmalloc,kfree需要这个文件引入
#include     //进程数据结构和操作
#include     //错误代码
#include        //文件操作;file_operation 结构,struct file,inode
#include      //字符设备结构,注册与销毁设备操作
#include     //dev_t 内核里代表设备号的类型.int MAJOR(dev_t dev)等
#include     //copy_to_user和copy_from_user
MODULE_AUTHOR("UserName");
MODULE_LICENSE("GPL");
static int hello_major = 0;              //设备文件主编号
static int hello_minor = 0;              // 设备文件次编号
static char *dev_name = "hello";         //显示的设备名称前缀
static int dev_count = 4;                //设备数量
static struct cdev **pDev = NULL;         //设备结构 集合

int hello_proc_open(struct inode *inode, struct file *filp);
ssize_t hello_proc_read(struct file *filp, char __user *buf, size_t count,loff_t *f_pos);
ssize_t hello_proc_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos);

static struct file_operations hello_proc_ops = {
.owner   = THIS_MODULE,                          //所属模块
.open    = hello_proc_open,                      //systemcall open
.read    = hello_proc_read,                      //systemcall read
.write =   hello_proc_write                      //systemcall write
};                                        //这里只进行打开,读取和写入操作示例
static int __init hello_init(void)
{
   dev_t dev = 0;
   int result = 0;
  // char* buf = NULL;
   int index;
   printk(KERN_ALERT "hello,kernel world\n");
   /*buf = kmalloc(BUFSIZE,0);
   if(buf != NULL)
   {
        memset(buf,0,BUFSIZE);
     memcpy(buf,"kmalloc memory successfully\n",strlen("kmalloc memory successfully\n"));
     printk(KERN_ALERT "%s\n", buf);
     kfree(buf);
     printk(KERN_ALERT "kfree memory successfully\n");
   }   */
   //获取字符设备主编号
   if (hello_major) {                                          
     dev = MKDEV(hello_major, hello_minor);                        
    register_chrdev_region(dev, dev_count, dev_name);
   }
   else {
     result = alloc_chrdev_region(&dev, hello_minor, dev_count,dev_name);
     hello_major = MAJOR(dev);
   }
   if (result
//为设备申结构请内存空间
  pDev = kmalloc(dev_count * sizeof(struct cdev*), GFP_KERNEL);
  //注册每个设备
  for (index = 0; indexowner = THIS_MODULE;
   pDev[index]->ops = &hello_proc_ops;
   err = cdev_add (pDev[index], devno, 1);               //注册设备
   if (err)
    printk(KERN_NOTICE "Error %d adding hello%d\n", err, index);
   else
   printk(KERN_NOTICE "Success %d adding hello%d\n", err, index);
  }
  return 0;
}
static void __exit hello_exit(void)
{
int i;
dev_t devno = MKDEV(hello_major, hello_minor);
/* Get rid of our char dev entries */
if (pDev) {
  for (i = 0; i
int hello_proc_open(struct inode *inode, struct file *filp)
{
  return 0;
}
ssize_t hello_proc_read(struct file *filp, char __user *buf, size_t count,loff_t *f_pos)
{
   int len = 0;
   unsigned long offset = 0;
   int remain = 0;
   struct task_struct *task;                         //进程或称任务结构
   for_each_process(task){                           //遍历当前的所有进程
      printk("[%s]%d\n",task->comm,task->pid);
   len = strlen(task->comm);
   remain = len;
   while (remain != 0)
   {
    remain = copy_to_user(buf + offset + len - remain ,task->comm + len - remain,remain);                                    //将进程名拷贝到用户空间  
   }
   offset += len;
   remain = 1;
   while (remain != 0)
   {
    remain = copy_to_user(buf + offset + 1-remain,"\n", remain);
   }
   offset += 1;
    }
remain = 1;
while (remain != 0)
{
  remain =  copy_to_user(buf + offset + 1-remain,"\0",remain);
}
printk("write to user count = [%lu]\n",offset + 1);
    return offset + 1;
}
ssize_t hello_proc_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
return 0;
}
module_init(hello_init);
module_exit(hello_exit);



Makefile

# Comment/uncomment the following line to disable/enable debugging
#DEBUG = y
# Add your debugging flag (or not) to CFLAGS
ifeq ($(DEBUG),y)
  DEBFLAGS = -O -g -Dhello_DEBUG # "-O" is needed to expand inlines
else
  DEBFLAGS = -O2
endif
CFLAGS += $(DEBFLAGS)
CFLAGS += -I$(LDDINC)
ifneq ($(KERNELRELEASE),)
# call from kernel build system
#hello-objs := hello.o
obj-m := hello.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD       := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) LDDINC=$(PWD)/../include modules
endif

clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
depend .depend dep:
$(CC) $(CFLAGS) -M *.c > .depend
ifeq (.depend,$(wildcard .depend))
include .depend
endif

加载hello设备脚本 hello_load
# invoke insmod with all arguments we got
# and use a pathname, as insmod doesn't look in . by default
/sbin/insmod ./$module.ko $* || exit 1
# retrieve major number
major=$(awk "\$2==\"$module\" {print \$1}" /proc/devices)
# Remove stale nodes and replace them, then give gid and perms
# Usually the script is shorter, it's hello that has several devices in it.
rm -f /dev/${device}[0-3]
mknod /dev/${device}0 c $major 0
mknod /dev/${device}1 c $major 1
mknod /dev/${device}2 c $major 2
mknod /dev/${device}3 c $major 3
ln -sf ${device}0 /dev/${device}
chgrp $group /dev/${device}[0-3]
chmod $mode  /dev/${device}[0-3]

卸载hello设备脚本 hello_unload

#!/bin/sh
module="hello"
device="hello"
# invoke rmmod with all arguments we got
/sbin/rmmod $module $* || exit 1
# Remove stale nodes
rm -f /dev/${device} /dev/${device}[0-3]


测试代码test.c:

#include
#include
#include
#include
#include
int main()
{
int fd = 0;
char buf[65535];
if((fd = open("/dev/hello1", O_CREAT|O_RDWR, 0644)) > 0)
{
  printf("open success.\n");
  read(fd,buf,65535);
  printf("%s\n",buf);
  close(fd);
}
else
{
  printf("open failed.\n");
}
return 0;
}


测试步骤:
编译后运行脚本hello_load,然后运行test,最后运行脚本 hello_unload,千万不要测试诸如cp /dev/hello1 a.txt, 因为该例子不完全,会导致无限循环。




本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/58955/showart_1193334.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP