操作系统实验指导书
(3)参考代码
函数scull_open()
int scull_open(struct inode *inode,struct file *filp) { MOD_INC_USE_COUNT;
// 增加该模块的用户数目 printk(“This chrdev is in open\\n”); return 0; }
函数scull_write() int scull_write
(struct inode *inode,struct file *filp,const char *buffer,int count) {
if(count < 0) return –EINVAL; if(scull.usage || scull.new_msg) return –EBUSY; scull.usage = 1; kfree(scull.data); data = kmalloc(sizeof(char)*(count+1),GFP_KERNEL); if(!scull.data) { return –ENOMEM; } copy_from_user(scull.data,buffer,count + 1);
33
操作系统实验指导书
scull.usage = 0; scull.new_msg = 1; return count; }
函数scull_read()
int scull_read(struct inode *inode,struct file *filp,char *buffer,int count) {
int length; if(count < 0) return –EINVAL; if(scull.usage) return –EBUSY; scull.usage = 1; if(scull.data == 0) return 0; length = strlen(scull.data); if(length < count) count = length; copy_to_user(buf,scull.data,count + 1); scull.new_msg = 0; scull.usage = 0; return count; }
函数scull_ioctl()
#include
#define SCULL_MAJOR 0 #define SCULL_MAGIC SCULL_MAJOR #define SCULL_RESET _IO(SCULL_MAGIC,0)
// 重置数据 #define SCULL_QUERY_NEW_MSG _IO(SCULL_MAGIC,1)
//检查新的消息 #define SCULL_QUERY_MSG_LENGTH _IO(SCULL_MAGIC,2) //获取消息长度 #define IOC_NEW_MSG 1
static int usage,new_msg; //控制标志 static char *data; int scull_ioctl
(struct inode *inode,struct file *filp,unsigned long int cmd,
unsigned long arg) { int ret=0; switch(cmd) {
case SCULL_RESET: kfree(data);
data = NULL; usage = 0;
new_msg = 0;
34
操作系统实验指导书
break;
case SCULL_QUERY_NEW_MSG: if(new_msg)
return IOC_NEW_MSG; break; case SCULL_QUERY_MSG_LENGTH: if(data == NULL){ return 0; } else {
return strlen(data); } break; default: return –ENOTTY; } return ret; }
函数scull_release()
void scull_release(struct inode *inode,struct file *filp) { MOD_DEC_USE_COUNT;
// 该模块的用户数目减1 printk(“This chrdev is in release\\n”); return 0; #ifdef DEBUG printk(“scull_release(%p,%p)\\n”,inode,filp); #endif }
4.2字符设备驱动程序的测试函数
(1)测试函数:
#cat /proc/devices | awk ”\\\\$2==\\ ”chrdev\\”{ print\\\\$1}” (2)字符设备驱动程序的测试函数流程图如图9.5所示。
35
操作系统实验指导书
(3)测试函数源代码testproc.c如下:
/************************************************************/ /***** testproc.c, this is a test program for chardev.c *****/ /************************************************************/
#include
#include “chardev.h” // /定义字符设备 void write_proc(void); void read_proc(void);
main(int argc,char **argv) { if(argc == 1) { puts(“syntax: testprog[write|read]\\n”); exit(0); } if(!strcmp(argv[1],“write”)) { write_porc(); }
36
操作系统实验指导书
else if(!strcmp(argv[1],“read”)) { read_proc(); } else { puts(“testprog: invalid command!\\n”); } return 0; }
void write_proc()
{
int fd,len,quit = 0; char buf[100]; fd = open(“/dev/chrdev”,O_WRONLY); if(fd <= 0) { printf(“Error opening device for writing!\\n”); exit(1); } while(!quit) {
printf(“\\n Please write into:”); gets(buf); if(!strcmp(buf,“exit”)) quit = 1; while(ioctl(fd,DYNCHAR_QUERY_NEW_MSG)) usleep(100); len = write(fd,buf,strlen(buf)); if(len < 0) { printf(“Error writing to device!\\n”); close(fd); exit(1); } printf(“\\n There are %d bytes written to device!\\n”,len);
} close(fd); }
void read_proc() { int fd,len,quit = 0; char *buf = NULL; fd=open(“/dev/chrdev”,O_RDONLY); if(fd < 0) { printf(“Error opening device for reading!\\n”); exit(1); } while(!quit) { printf(“\\n Please read out:”); while(!ioctl(fd,DYNCHAR_QUERY_NEW_MSG))
37
操作系统实验指导书
usleep(100); // 获取消息长度。 len = ioctl(fd,DYNCHAR_QUERY_MSG_LENGTH,NULL);
if(len) { if(buf != NULL) free(buf); buf = malloc(sizeof(char)*(len+1)); len = read(fd,buf,len); if(len < 0) { printf(“Error reading from device!\\n”); }
else { if(!strcmp(buf,“exit”) { ioctl(fd,DYNCHAR_RESET);
// 字符设备复位 quit = 1;
} else
printf(“%s\\n”,buf); } } } free(buf); close(fd); }
// 以下为chrdev.h定义 #ifndef _DYNCHAR_DEVICE_H #define _DYNCHAR_DEVICE_H #include
#define DYNCHAR_MAGIC DYNCHAR_MAJOR
#define DYNCHAR_RESET _IO(DYNCHAR_MAGIC,0) // 重置数据
#define DYNCHAR_QUERY_NEW_MSG _IO(DYNCHAR_MAGIC,1) // 检查新的消息 #define DYNCHAR_QUERY_MSG_LENGTH _IO(DYNCHAR_MAGIC,2) // 获取消息长度#define IOC_NEW_MSG 1 #endif
5.拓展训练
思考:块设备的驱动程序又该如何实现?
38