免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4648 | 回复: 3
打印 上一主题 下一主题

关于字符设备驱动程序的开发(学校做的课程设计) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-05-06 20:16 |只看该作者 |倒序浏览
题目:设计和实现一个虚拟命名管道(FIFO)的字符设备。我们知道,管道是进程间通信的一种
方式:一个进程向管道中写数据,另一个进程从管道中读取数据,先写入的数据先读出。我
们的驱动程序要实现N(N=4)个管道,每个管道对应两个设备,次设备号是偶数的设备是只
写设备,次设备号是奇数的是只读设备。写入设备i(i是偶数)的字符可以从设备i+1读出。
这样,我们一共就需要2N 个次设备号。
我们的目标是写一个模块化的字符设备驱动程序。设备所使用的主设备号可以从尚未分
配的主设备号中任选一个,/Documentation/devices.txt 记录了当前版本内核的主设备号分配
情况。如果设备文件系统(devfs)尚未激活,我们在加载模块之后,还必须用mknod 命令创
建相应的设备文件节点。
如果 FIFO 的写入端尚未打开,FIFO 中就不会有数据可读,所以此时试图从FIFO 中读
取数据的进程应该返回一个错误码。如果写入端已经打开,为了保证对临界区的互斥访问,
调用读操作的进程必须被阻塞。如果存在被阻塞的读者,在写操作完成后(或者关闭一个写
设备时)必须唤醒它。
如果写入的数据太多,超出了缓冲区中空闲块的大小,调用写操作的进程必须睡眠,以
等待缓冲区中有新的空闲块。

论坛徽章:
0
2 [报告]
发表于 2011-05-06 20:17 |只看该作者
#ifndef   __KERNEL__     
#define   __KERNEL__
#endif
#ifndef   MODULE
#define   MODULE
#endif
#define   __NO__VERSION__
#include   <linux/config.h>
#include   <linux/module.h>
#include   <linux/kernel.h>
#include   <linux/slab.h>
#include   <linux/fs.h>
#include   <linux/proc_fs.h>
#include   <linux/errno.h>
#include   <linux/types.h>
#include   <linux/fcntl.h>
#include   <linux/init.h>
#include   <linux/poll.h>
#include   <asm/uaccess.h>
#include   <asm/system.h>
#ifndef   VFIFO_MAJOR
#define   VFIFO_MAJOR     241
#endif
#ifndef   VFIFO_NR_DEVS
#define   VFIFO_NR_DEVS     4
#endif
#ifndef   VFIFO_BUFFER
#define   VFIFO_BUFFER   4000
#endif
#include   <linux/devfs_fs_kernel.h>
devfs_handle_t   vfifo_devfs_dir;
int   vfifo_major=VFIFO_MAJOR;
int   vfifo_nr_devs=VFIFO_NR_DEVS;
int   vfifo_buffer=VFIFO_BUFFER;
MODULE_PARM(vfifo_major, "i ");
MODULE_PARM(vfifo_nr_devs, "i ");
MODULE_PARM(vfifo_buffer, "i ");
MODULE_AUTHOR( "CODEPRIMER ");

typedef   struct   Vfifo_Dev{
wait_queue_head_t   rdq,wrq;         //   rdq表示堵塞读的等待队列,wrq是堵塞写的等待队列
char   *base;                               //所分配缓冲区的起始地址
unsigned   int   buffersize;     //是缓冲区的大小
unsigned   int   len;                     //表示管道中已有数据块的长度
unsigned   int   start;               //应该读取得缓冲区位置相对于base的偏移量
unsigned   int   readers,writers;   
//表示VFIFO设备当前的读者个数和写着个数
struct   semaphore   sem;                   //用于互斥的访问的信号量
devfs_handle_t   r_handle,w_handle;   //用于保存设备文件系统的注册句柄,前者表示只读设备,后者表示同一管道的只写设备
}Vfifo_Dev;
struct   Vfifo_Dev   *vfifo_devices;
char   vfifoname[8];


static   int   vfifo_open(struct   inode   *inode,struct   file   *filp)
{
Vfifo_Dev   *dev;
int   num=MINOR(inode-> i_rdev);
if(!filp-> private_data)
{
if   (num> =vfifo_nr_devs*2)       
return   -ENODEV;
dev=&vfifo_devices[num/2];
filp-> private_data=dev;
}else{       
dev=filp-> private_data;
}
if   (down_interruptible(&dev-> sem))
return   -ERESTARTSYS;
if(!dev-> base){
dev-> base=kmalloc(vfifo_buffer,GFP_KERNEL);
if(!dev-> base){       
up(&dev-> sem);
return   -ENOMEM;       
}
dev-> buffersize=vfifo_buffer;
dev-> len=dev-> start=0;
}
if(filp-> f_mode   &   FMODE_READ)        //****
dev-> readers++;
if(filp-> f_mode   &   FMODE_WRITE)        dev-> writers++;     //****
filp-> private_data=dev;                 
MOD_INC_USE_COUNT;
up(&dev-> sem);
return   0;
}


static   int   vfifo_release(struct   inode   *inode,struct   file   *filp)
{
Vfifo_Dev   *dev=filp-> private_data;
down(&dev-> sem);
if(filp-> f_mode&FMODE_READ)
dev-> readers--;
if(filp-> f_mode&FMODE_WRITE){
dev-> writers--;       
wake_up_interruptible(&dev-> sem.wait);
}       
if((dev-> readers+dev-> writers==0)&&(dev-> len==0)){       
kfree(dev-> base);
dev-> base=NULL;
}
up(&dev-> sem);
MOD_DEC_USE_COUNT;
return   0;
}
static   ssize_t   vfifo_read(struct   file   *filp,char   *buf,size_t   count,loff_t   *f_pos)
{
Vfifo_Dev   *dev=filp-> private_data;
ssize_t   read=0;
if(f_pos!=&filp-> f_pos)       //****
return   -ESPIPE;
if(down_interruptible(&dev-> sem))
return   -ERESTARTSYS;
do_more_read:
while(dev-> len==0){
if(!dev-> writers){
                        up(&dev-> sem);       
                        return   -EAGAIN;
}
up(&dev-> sem);
                if(filp-> f_flags&O_NONBLOCK)
return   -EAGAIN;       
    printk( "%s   reading:going   to   sleep\n ",current-> comm);
if(wait_event_interruptible(dev-> rdq,(dev-> len> 0)))
return   -ERESTARTSYS;
printk( "%s   has   been   waken   up\n ",current-> comm);
if(down_interruptible(&dev-> sem))
return   -ERESTARTSYS;        }

while(count> 0&&dev-> len){
char   *pipebuf=dev-> base+dev-> start;
              ssize_t   chars=dev-> buffersize-dev-> start;
if(chars> count)   chars=count;
if(chars> dev-> len)   chars=dev-> len;
if(copy_to_user(buf,pipebuf,chars)){
up(&dev-> sem);
return   -EFAULT;
}       
read+=chars;
dev-> start+=chars;
dev-> start%=dev-> buffersize;
dev-> len-=chars;
count-=chars;
buf+=chars;
}       
  if   (!dev-> len)   dev-> start=0;
                if(count   &&   dev-> writers   &&   !(filp-> f_flags   &   O_NONBLOCK)){               //****
up(&dev-> sem);
wake_up_interruptible(&dev-> wrq);
if(down_interruptible(&dev-> sem))
return   -ERESTARTSYS;
goto   do_more_read;
}
up(&dev-> sem);
wake_up_interruptible(&dev-> wrq);
                printk( "%s   did   read   %d   bytes\n ",current-> comm,   read);         //****
return   read;
}


static   ssize_t   vfifo_write(struct   file   *filp,const   char   *buf,size_t   count,loff_t   *f_pos)
{       
Vfifo_Dev   *dev=filp-> private_data;
ssize_t   written=0;
if(f_pos!=&filp-> f_pos||count==0)
return   -ESPIPE;
if(down_interruptible(&dev-> sem))
return   -ERESTARTSYS;
do_more_write:
while(dev-> len==dev-> buffersize){
up(&dev-> sem);
if(filp-> f_flags&O_NONBLOCK)
return   -EAGAIN;
printk( "%s   writting:going   to   sleep\n ",current-> comm);       

if(wait_event_interruptible(dev-> wrq,(dev-> len <dev-> buffersize)))
return   -ERESTARTSYS;
printk( "%s   has   been   waken   up\n ",current-> comm);
if(down_interruptible(&dev-> sem))
return   -ERESTARTSYS;
}

while(count> 0){
char   *pipebuf=
                dev-> base+(dev-> len+dev-> start)%dev-> buffersize;
ssize_t   chars=dev-> buffersize-(dev-> len+dev-> start);
if(chars <0)   chars+=dev-> start;
if(chars!=0)   {
if   (chars> count)   chars=count;       
if   (copy_from_user(pipebuf,buf,chars)){
up(&dev-> sem);
return   -EFAULT;
}
written+=chars;
dev-> len+=chars;
count-=chars;
buf+=chars;
}
}
if   (count&&!(filp-> f_flags&O_NONBLOCK)){
up(&dev-> sem);
wait_up_interruptible(&dev-> rdq);         //****   ???
if   (down_interruptible(&dev-> sem))       
return   -ERESTARTSYS;
goto   do_more_write;
}
up(&dev-> sem);
wake_up_interruptible(&dev-> rdq);     //****     ???
printk( "%s   did   write   %i   bytes\n ",current-> comm,   written);         //****
return   written;
}


unsigned   int   vfifo_poll(struct   file   *filp,poll_table   *wait)
{
Vfifo_Dev   *dev=filp-> private_data;
unsigned   int   mask=0;
poll_wait(filp,&dev-> rdq,wait);
poll_wait(filp,&dev-> wrq,wait);
if   (dev-> len> 0)   mask|=POLLIN|POLLRDNORM;
if   (dev-> len!=dev-> buffersize)   mask|=POLLOUT|POLLWRNORM;
return   mask;
}


static   struct   file_operations   vfifo_fops={
read:     vfifo_read,
write:   vfifo_write,
poll:   vfifo_poll,
                open:   vfifo_open,
release:vfifo_release,
};


static   int   __init   vfifo_init_module(void)
{
int   result,i;
SET_MODULE_OWNER(&vfifo_fops);
#ifdef   CONFIG_DEVFS_FS       
vfifo_devfs_dir=devfs_mk_dir(NULL, "vfifo ",NULL);
if(!vfifo_devfs_dir)
return   -EBUSY;
#endif
result=devfs_register_chrdev(vfifo_major, "vfifo ",&vfifo_fops);
if   (result <0){
printk(KERN_WARNING   "vfifo:can 't   get   major   %d\n ",vfifo_major);
return   result;
}
if   (vfifo_major==0)       
vfifo_major=result;
vfifo_devices=kmalloc(vfifo_nr_devs*sizeof(Vfifo_Dev),GFP_KERNEL);
if   (!vfifo_devices){
return   -ENOMEM;
}
memset(vfifo_devices,0,vfifo_nr_devs*sizeof(Vfifo_Dev));
for   (i=0;i <vfifo_nr_devs;i++){
init_waitqueue_head(&vfifo_devices[i].rdq);
init_waitqueue_head(&vfifo_devices[i].wrq);
sema_init(&vfifo_devices[i].sem,1);
#ifdef   CONFIG_DEVFS_FS
sprintf(vfifoname, "vfifo%d ",2*i+1);
vfifo_devices[i].w_handle=                      
devfs_register(vfifo_devfs_dir,vfifoname,DEVFS_FL_NON,vfifo_major,2*i,S_IFCHR|S_IRUGO|S_IWUGO,&vfifo_fops,vfifo_devices+i);
                sprintf(vfifoname, "vfifo%d ",2*i+1);
vfifo_devices[i].r_handle=       

devfs_register(vfifo_devfs_dir,vfifoname,DEVFS_FL_NON,vfifo_major,2*i+1,S_IFCHR|S_IRUGO|S_IWUGO,&vfifo_fops,vfifo_devices+i);       

if   (!vfifo_devices[i].r_handle||!vfifo_devices[i].w_handle){
printk(KERN_WARNING   "vfifo:   can 't   register   vfifo   device   nr   %i\n ",i);
}
#endif                                 
}
#ifdef   VFIFO_DEBUG
  create_proc_read_entry( "vfifo ",0,NULL,vfifo_read_mem,NULL);
#endif   
return   0;
}

static   void   __exit   vfifo_cleanup_module(void)
{
int   i;
devfs_unregister_chrdev(vfifo_major, "vfifo ");
#ifdef   VFIFO_DEBUG       
remove_proc_entry( "vfifo ",NULL);                     
#endif
if   (vfifo_devices){
for   (i=0;i <vfifo_nr_devs;i++){               
if   (vfifo_devices[i].base)
kfree(vfifo_devices[i].base);
devfs_unregister(vfifo_devices[i].r_handle);
devfs_unregister(vfifo_devices[i].w_handle);
}
kfree(vfifo_devices);
devfs_unregister(vfifo_devfs_dir);
}
}

module_init(vfifo_init_module);
module_exit(vfifo_cleanup_module);

论坛徽章:
0
3 [报告]
发表于 2011-05-06 20:19 |只看该作者
在Ubuntu中的vi编辑器编译后、出现如下的错误:(我新手、完全看不懂啊~~~求助)
xianan@xianan-desktop:~$ gcc -c vfifo.c -D_KERNEL_-DMODULE -o2 -g -Wall
<command-line>: warning: missing whitespace after the macro name
vfifo.c:8:29: error: linux/config.h: No such file or directory
vfifo.c:9:29: error: linux/module.h: No such file or directory
vfifo.c:11:27: error: linux/slab.h: No such file or directory
vfifo.c:13:30: error: linux/proc_fs.h: No such file or directory
In file included from /usr/include/asm/fcntl.h:1,
                 from /usr/include/linux/fcntl.h:4,
                 from vfifo.c:16:
/usr/include/asm-generic/fcntl.h:96: error: expected specifier-qualifier-list before ‘pid_t’
vfifo.c:17:27: error: linux/init.h: No such file or directory
vfifo.c:19:28: error: asm/uaccess.h: No such file or directory
vfifo.c:20:27: error: asm/system.h: No such file or directory
vfifo.c:30:38: error: linux/devfs_fs_kernel.h: No such file or directory
vfifo.c:31: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘vfifo_devfs_dir’
vfifo.c:35: error: expected ‘)’ before string constant
vfifo.c:36: error: expected ‘)’ before string constant
vfifo.c:37: error: expected ‘)’ before string constant
vfifo.c:38: error: expected declaration specifiers or ‘...’ before string constant
vfifo.c:38: warning: data definition has no type or storage class
vfifo.c:38: warning: type defaults to ‘int’ in declaration of ‘MODULE_AUTHOR’
vfifo.c:41: error: expected specifier-qualifier-list before ‘wait_queue_head_t’
vfifo.c:55: warning: ‘struct file’ declared inside parameter list
vfifo.c:55: warning: its scope is only this definition or declaration, which is probably not what you want
vfifo.c:55: warning: ‘struct inode’ declared inside parameter list
vfifo.c: In function ‘vfifo_open’:
vfifo.c:58: warning: implicit declaration of function ‘MINOR’
vfifo.c:58: error: dereferencing pointer to incomplete type
vfifo.c:59: error: dereferencing pointer to incomplete type
vfifo.c:61: error: expected expression before ‘=’ token
vfifo.c:64: error: dereferencing pointer to incomplete type
vfifo.c:66: error: dereferencing pointer to incomplete type
vfifo.c:68: warning: implicit declaration of function ‘down_interruptible’
vfifo.c:68: error: ‘Vfifo_Dev’ has no member named ‘sem’
vfifo.c:69: error: ‘ERESTARTSYS’ undeclared (first use in this function)
vfifo.c:69: error: (Each undeclared identifier is reported only once
vfifo.c:69: error: for each function it appears in.)
vfifo.c:70: error: ‘Vfifo_Dev’ has no member named ‘base’
vfifo.c:71: error: ‘Vfifo_Dev’ has no member named ‘base’
vfifo.c:71: warning: implicit declaration of function ‘kmalloc’
vfifo.c:71: error: ‘GFP_KERNEL’ undeclared (first use in this function)
vfifo.c:72: error: ‘Vfifo_Dev’ has no member named ‘base’
vfifo.c:73: warning: implicit declaration of function ‘up’
vfifo.c:73: error: ‘Vfifo_Dev’ has no member named ‘sem’
vfifo.c:76: error: ‘Vfifo_Dev’ has no member named ‘buffersize’
vfifo.c:77: error: ‘Vfifo_Dev’ has no member named ‘len’
vfifo.c:77: error: ‘Vfifo_Dev’ has no member named ‘start’
vfifo.c:79: error: dereferencing pointer to incomplete type
vfifo.c:79: error: ‘fmode_t’ undeclared (first use in this function)
vfifo.c:79: error: expected ‘)’ before numeric constant
vfifo.c:80: error: ‘Vfifo_Dev’ has no member named ‘readers’
vfifo.c:81: error: dereferencing pointer to incomplete type
vfifo.c:81: error: expected ‘)’ before numeric constant
vfifo.c:81: error: ‘Vfifo_Dev’ has no member named ‘writers’
vfifo.c:82: error: dereferencing pointer to incomplete type
vfifo.c:83: error: ‘MOD_INC_USE_COUNT’ undeclared (first use in this function)
vfifo.c:84: error: ‘Vfifo_Dev’ has no member named ‘sem’
vfifo.c: At top level:
vfifo.c:89: warning: ‘struct file’ declared inside parameter list
vfifo.c:89: warning: ‘struct inode’ declared inside parameter list
vfifo.c: In function ‘vfifo_release’:
vfifo.c:91: error: dereferencing pointer to incomplete type
vfifo.c:92: warning: implicit declaration of function ‘down’
vfifo.c:92: error: ‘Vfifo_Dev’ has no member named ‘sem’
vfifo.c:93: error: dereferencing pointer to incomplete type
vfifo.c:93: error: ‘fmode_t’ undeclared (first use in this function)
vfifo.c:93: error: expected ‘)’ before numeric constant
vfifo.c:94: error: ‘Vfifo_Dev’ has no member named ‘readers’
vfifo.c:95: error: dereferencing pointer to incomplete type
vfifo.c:95: error: expected ‘)’ before numeric constant
vfifo.c:96: error: ‘Vfifo_Dev’ has no member named ‘writers’
vfifo.c:97: warning: implicit declaration of function ‘wake_up_interruptible’
vfifo.c:97: error: ‘Vfifo_Dev’ has no member named ‘sem’
vfifo.c:99: error: ‘Vfifo_Dev’ has no member named ‘readers’
vfifo.c:99: error: ‘Vfifo_Dev’ has no member named ‘writers’
vfifo.c:99: error: ‘Vfifo_Dev’ has no member named ‘len’
vfifo.c:100: warning: implicit declaration of function ‘kfree’
vfifo.c:100: error: ‘Vfifo_Dev’ has no member named ‘base’
vfifo.c:101: error: ‘Vfifo_Dev’ has no member named ‘base’
vfifo.c:103: error: ‘Vfifo_Dev’ has no member named ‘sem’
vfifo.c:104: error: ‘MOD_DEC_USE_COUNT’ undeclared (first use in this function)
vfifo.c: At top level:
vfifo.c:107: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘vfifo_read’
vfifo.c:162: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘vfifo_write’
vfifo.c:215: error: expected declaration specifiers or ‘...’ before ‘poll_table’
vfifo.c:215: warning: ‘struct file’ declared inside parameter list
vfifo.c: In function ‘vfifo_poll’:
vfifo.c:217: error: dereferencing pointer to incomplete type
vfifo.c:219: warning: implicit declaration of function ‘poll_wait’
vfifo.c:219: error: ‘Vfifo_Dev’ has no member named ‘rdq’
vfifo.c:219: error: ‘wait’ undeclared (first use in this function)
vfifo.c:220: error: ‘Vfifo_Dev’ has no member named ‘wrq’
vfifo.c:221: error: ‘Vfifo_Dev’ has no member named ‘len’
vfifo.c:222: error: ‘Vfifo_Dev’ has no member named ‘len’
vfifo.c:222: error: ‘Vfifo_Dev’ has no member named ‘buffersize’
vfifo.c: At top level:
vfifo.c:227: error: variable ‘vfifo_fops’ has initializer but incomplete type
vfifo.c:228: error: unknown field ‘read’ specified in initializer
vfifo.c:228: error: ‘vfifo_read’ undeclared here (not in a function)
vfifo.c:228: warning: excess elements in struct initializer
vfifo.c:228: warning: (near initialization for ‘vfifo_fops’)
vfifo.c:229: error: unknown field ‘write’ specified in initializer
vfifo.c:229: error: ‘vfifo_write’ undeclared here (not in a function)
vfifo.c:229: warning: excess elements in struct initializer
vfifo.c:229: warning: (near initialization for ‘vfifo_fops’)
vfifo.c:230: error: unknown field ‘poll’ specified in initializer
vfifo.c:230: warning: excess elements in struct initializer
vfifo.c:230: warning: (near initialization for ‘vfifo_fops’)
vfifo.c:231: error: unknown field ‘open’ specified in initializer
vfifo.c:231: warning: excess elements in struct initializer
vfifo.c:231: warning: (near initialization for ‘vfifo_fops’)
vfifo.c:232: error: unknown field ‘release’ specified in initializer
vfifo.c:232: warning: excess elements in struct initializer
vfifo.c:232: warning: (near initialization for ‘vfifo_fops’)
vfifo.c:236: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘vfifo_init_module’
vfifo.c:281: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘vfifo_cleanup_module’
vfifo.c:300: warning: data definition has no type or storage class
vfifo.c:300: warning: type defaults to ‘int’ in declaration of ‘module_init’
vfifo.c:300: warning: parameter names (without types) in function declaration
vfifo.c:301: warning: data definition has no type or storage class
vfifo.c:301: warning: type defaults to ‘int’ in declaration of ‘module_exit’
vfifo.c:301: warning: parameter names (without types) in function declaration

论坛徽章:
0
4 [报告]
发表于 2011-05-06 20:20 |只看该作者
希望哪位高手帮我解决下、谢谢了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP