scull

第一部分 字符设备驱动程序

1.1 函数scull_open()

int scull_open(struct inode *inode,struct file *filp) {

MOD_INC_USE_COUNT; // 增加该模块的用户数目

printk(“This chrdev is in open\n”);

return 0;

}

1.2 函数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);

scull.usage = 0;

scull.new_msg = 1;

return count;

}

1.3 函数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;

}

1.4 函数scull_ioctl()

#include <linux/ioctl.h>

#define SCULL_MAJOR 0

#define SCULL_MAGIC SCULL_MAJOR

#define SCULL_RESET _IO(SCULL_MAGIC,0) // reset the data

#define SCULL_QUERY_NEW_MSG _IO(SCULL_MAGIC,1) // check for new message

#define SCULL_QUERY_MSG_LENGTH _IO(SCULL_MAGIC,2) //get message length

#define IOC_NEW_MSG 1

static int usage,new_msg; // control flags

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;

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;

}

1.5 函数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

}

1.6 测试函数

在该字符设备驱动程序编译加载后,再在/dev目录下创建字符设备文件chrdev,使用命令: #mknod /dev/chrdev c major minor ,其中“c”表示chrdev是字符设备,“major”是chrdev的主设备号。(该字符设备驱动程序编译加载后,可在/proc/devices文件中获得主设备号,或者使用命令: #cat /proc/devices | awk ”\\$2==”chrdev\”{ print\\$1}” 获得主设备号)

#include <stdio.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <sys/ioctl.h>

#include <stdlib.h>

#include <string.h>

#include <fcntl.h>

#include <unistd.h>

#include <errno.h>

#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();

}

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))

usleep(100);

// get the msg length

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); // reset

quit = 1;

}

else

printf(“%s\n”,buf);

}

}

}

free(buf);

close(fd);

}

// 以下为chrdev.h定义

#ifndef _DYNCHAR_DEVICE_H

#define _DYNCHAR_DEVICE_H

#include <linux/ioctl.h>

#define DYNCHAR_MAJOR 42

#define DYNCHAR_MAGIC DYNCHAR_MAJOR

#define DYNCHAR_RESET _IO(DYNCHAR_MAGIC,0) // reset the data

#define DYNCHAR_QUERY_NEW_MSG _IO(DYNCHAR_MAGIC,1) // check for new message

#define DYNCHAR_QUERY_MSG_LENGTH _IO(DYNCHAR_MAGIC,2) // get message length

#define IOC_NEW_MSG 1

#endif
流氓 北京旅游景点 赛马 上海滩主题曲 上海房产网 托福培训 陈奕 龙帝至尊 江汉热线 心痛的句子 道光皇帝 600108 成贵高铁 杨雄 天安门升旗时间 情欲小说 曾经的你歌词 邪魅毒医御七夫 柴可夫斯基 光荣 读者和主角绝壁是真爱 blessing 太子妃升职记好看吗 脑心通胶囊 斯琴格日乐 新疆美女 詹妮弗·康纳利 甜点

Copyright 魔方网 Some Rights Reserved

如反馈或投诉等情况联系:une35498#163.com