关于字符设备驱动程序的开发(学校做的课程设计)
题目:设计和实现一个虚拟命名管道(FIFO)的字符设备。我们知道,管道是进程间通信的一种
方式:一个进程向管道中写数据,另一个进程从管道中读取数据,先写入的数据先读出。我
们的驱动程序要实现N(N=4)个管道,每个管道对应两个设备,次设备号是偶数的设备是只
写设备,次设备号是奇数的是只读设备。写入设备i(i是偶数)的字符可以从设备i+1读出。
这样,我们一共就需要2N 个次设备号。
我们的目标是写一个模块化的字符设备驱动程序。设备所使用的主设备号可以从尚未分
配的主设备号中任选一个,/Documentation/devices.txt 记录了当前版本内核的主设备号分配
情况。如果设备文件系统(devfs)尚未激活,我们在加载模块之后,还必须用mknod 命令创
建相应的设备文件节点。
如果 FIFO 的写入端尚未打开,FIFO 中就不会有数据可读,所以此时试图从FIFO 中读
取数据的进程应该返回一个错误码。如果写入端已经打开,为了保证对临界区的互斥访问,
调用读操作的进程必须被阻塞。如果存在被阻塞的读者,在写操作完成后(或者关闭一个写
设备时)必须唤醒它。
如果写入的数据太多,超出了缓冲区中空闲块的大小,调用写操作的进程必须睡眠,以
等待缓冲区中有新的空闲块。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
#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);
在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
希望哪位高手帮我解决下、谢谢了。