驱动代码如下:

scull.c

#include

#include

#include

#include

#include

#include

#include

#include

#defineSCULL_MAJOR252

#define SCULL_NAME"scull"

#define MAX_DATA0x10

staticint scull_major = SCULL_MAJOR;

struct scull_dev {

struct cdev cdev;

unsigned char data[MAX_DATA];

struct semaphore sem;

unsigned int current_len;

wait_queue_head_t r_wait;

wait_queue_head_t w_wait;

};

MODULE_LICENSE("GPL");

MODULE_AUTHOR("BG2BKK");

structscull_dev *scull_devp;

intscull_open(struct inode *inode, struct file *filp)

{

struct scull_dev *dev = container_of(inode->i_cdev, struct scull_dev, cdev);

filp->private_data = dev;

printk(KERN_ALERT "open the scull device\n");

return 0;

}

intscull_release(struct inode *inode, struct file *filp)

{

printk(KERN_ALERT "close the scull device\n");

return 0;

}

ssize_tscull_read(struct file *filp, char __user *buf, size_t count, loff_t *f_ops)

{

struct scull_dev *dev = filp->private_data;

int ret = 0;

DECLARE_WAITQUEUE(wait, current);

down(&dev->sem);

add_wait_queue(&dev->r_wait, &wait);

while(dev->current_len == 0)

{

if(filp->f_flags & O_NONBLOCK)

{

ret = -EAGAIN;

goto out;

}

__set_current_state(TASK_INTERRUPTIBLE);

up(&dev->sem);

schedule();

if(signal_pending(current)){

ret = -ERESTARTSYS;

goto out2;

}

down(&dev->sem);

}

if(count > dev->current_len)

count = dev->current_len;

if(copy_to_user(buf, dev->data,count)){

ret = -EFAULT;

goto out;

} else {

memcpy(dev->data, dev->data + count, dev->current_len - count);

dev->current_len -= count;

printk(KERN_ALERT "read %u bytes; current_len:%d\n",count, dev->current_len);

wake_up_interruptible(&dev->w_wait);

ret = count;

}

out:

up(&dev->sem);

out2:

remove_wait_queue(&dev->w_wait, &wait);

set_current_state(TASK_RUNNING);

return ret;

}

ssize_t scull_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_ops)

{

struct scull_dev *dev = filp->private_data;

int ret = 0;

DECLARE_WAITQUEUE(wait, current);

down(&dev->sem);

add_wait_queue(&dev->w_wait, &wait);

while(dev->current_len == MAX_DATA){

if(filp->f_flags & O_NONBLOCK){

ret = -EAGAIN;

goto out;

}

__set_current_state(TASK_INTERRUPTIBLE);

up(&dev->sem);

schedule();

if(signal_pending(current)){

ret = -ERESTARTSYS;

goto out2;

}

down(&dev->sem);

}

if(count > MAX_DATA - dev->current_len){

count = MAX_DATA - dev->current_len;

}

if(copy_from_user(dev->data + dev->current_len, buf, count)){

ret = -EFAULT;

goto out;

}

else {

dev->current_len += count;

printk(KERN_ALERT "written %d bytes, current_len:%d\n",count, dev->current_len);

wake_up_interruptible(&dev->r_wait);

ret = count;

}

out:

up(&dev->sem);

out2:

remove_wait_queue(&dev->w_wait, &wait);

set_current_state(TASK_RUNNING);

return ret;

}

staticunsigned int scull_poll(struct file *filp, poll_table *wait)

{

unsigned int mask = 0;

struct scull_dev *dev = filp->private_data;

down(&dev->sem);

poll_wait(filp, &dev->r_wait, wait);

poll_wait(filp, &dev->w_wait, wait);

if(dev->current_len != 0)

mask |= POLLIN | POLLRDNORM;

if(dev->current_len != MAX_DATA)

mask |= POLLOUT | POLLWRNORM;

up(&dev->sem);

return mask;

}

static const structfile_operations scull_fops = {

.owner=THIS_MODULE,

.open=scull_open,

.release=scull_release,

.write=scull_write,

.read=scull_read,

.poll=scull_poll,

};

staticvoidscull_setup_cdev(struct scull_dev *dev, int index)

{

int err, devno = MKDEV(scull_major, index);

cdev_init(&dev->cdev, &scull_fops);

dev->cdev.owner = THIS_MODULE;

err = cdev_add(&dev->cdev, devno, 1);

if(err)

printk(KERN_NOTICE "ERROR %d adding scull_dev %d", err, index);

}

intscull_init(void)

{

int result;

dev_tdevno = MKDEV(scull_major,0);

if(scull_major)

result = register_chrdev_region(devno, 1, "scull");

else {

result = alloc_chrdev_region(&devno, 0, 1, "scull");

scull_major = MAJOR(devno);

}

if(result < 0)

return result;

scull_devp = kmalloc(sizeof(struct scull_dev), GFP_KERNEL);

if(!scull_devp){

result = -ENOMEM;

goto fail_malloc;

}

memset(scull_devp, 0 , sizeof(struct scull_dev));

scull_setup_cdev(scull_devp, 0);

init_MUTEX(&scull_devp->sem);

init_waitqueue_head(&scull_devp->r_wait);

init_waitqueue_head(&scull_devp->w_wait);

printk(KERN_ALERT "init scull device\n");

return 0;

fail_malloc:

unregister_chrdev_region(devno, 1);

return result;

}

voidscull_cleanup(void)

{

cdev_del(&scull_devp->cdev);

kfree(scull_devp);

unregister_chrdev_region(MKDEV(scull_major, 0), 1);

printk(KERN_ALERT "clean scull device\n");

}

module_init(scull_init);

module_exit(scull_cleanup);测试代码

/*************************************************************************

*fileName: test.c

*description: test the myscull.c

*author: Hzc

*create time: 2007-04-20

*modify info: -

*************************************************************************/

#include

#include

#include

#include

#include

#include

#define BUFFER_LEN 20

#define FIFO_CLEAR 0x01

#define device"/dev/scull"

int main()

{

int num;

fd_set rfds, wfds;

int fd = open(device, O_RDONLY| O_NONBLOCK);

if(fd != 0){

while(1){

FD_ZERO(&rfds);

FD_ZERO(&wfds);

FD_SET(fd, &rfds);

FD_SET(fd, &wfds);

select(fd+1, &rfds, &wfds, NULL, NULL);

if(FD_ISSET(fd, &rfds))

printf("poll monitor: can be read\n");

if(FD_ISSET(fd, &wfds))

printf("poll monitor: can be written\n");

}

} else{

printf("Device " device "open failer");

}

}

Makefile

KERNEL_DIR := /lib/modules/$(shell uname -r)/build

PWD:= $(shell pwd)

obj-m := scull.o

default:

$(MAKE) -C $(KERNEL_DIR) SUBDIRS=$(PWD) modules

test: test.c

gcc $< -o $@.o -g

clean:

rm -rf *.o *.ko *~ *.order *.symvers *.markers *.mod.c

测试脚本

1 load_scull.sh

#!/bin/sh

/sbin/insmod scull.ko

mknod /dev/scull c 252 0

2 unload_scull.sh

#!/bin/sh

/sbin/rmmod scull.ko

rm /dev/scull -f

3 test.sh

#!/bin/sh

make clean

make

make test

sudo ./unload_scull

sudo ./load_scull

sudo ./test.o

测试时,执行./test.o,终端一直输出poll monitor: can be write,

在另一终端,以根用户模式,echo hello > /dev/scull,可以看到输出poll monitor: can be read和poll monitor: can be write

多echo hello > /dev/scull几次后,由于scull设备缓冲区仅16B,不再能写入,此时只输出poll monitor: can be read

宋宝华linux内核驱动代码,宋宝华 《Linux设备驱动开发详解》示例代码之fifo字符设备驱动...相关推荐

  1. linux svn 增量备份脚本,svn全量和增量备份详解(示例代码)

    1.svn的安装: yum安装: yum install -y subversion mkdir /data/svn svnadmin create project-1 svnadmin create ...

  2. python哪个代码是正确的字典_Python - 字典(dict) 详解 及 代码

    字典(dict) 详解 及 代码 本文地址: http://blog.csdn.net/caroline_wendy/article/details/17291329 字典(dict)是表示映射的数据 ...

  3. 贪心算法思想详解+示例代码

    CSDN话题挑战赛第2期 参赛话题:学习笔记 文章目录 五大算法思想 贪心算法 举例说明 选择排序 删除数字 寻找数字最大和 买股票 最大回文字符串 背包问题 小结 五大算法思想 分治思想 贪心算法/ ...

  4. Linux内核中kzalloc分配内存时用的参数GFP_KERNEL详解

    简介 GFP(Get Free Pages缩写)在include/linux/gfp.h中定义. GFP_KERNEL 是内核内存分配时最常用的,无内存可用时可引起休眠. GFP_ATOMIC 用来从 ...

  5. linux ps 代码,Linux ps命令详解(示例代码)

    ps命令是Process Status的缩写, 用来列出系统中当前运行的那些进程. ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,如果想要动态的显示进程信息,就可以使用to ...

  6. linux中代码挂上n,Linux系统常用命令nl详解(示例代码)

    nl命令在linux系统中用来计算文件中行号.nl可以将输出的文件内容自动的加上行号!其默认的结果与cat -n有点不太一样,nl可以将行号做比较多的显示设计,包括位数与是否自动补齐0等等的功能.本文 ...

  7. linux文件属性644到755,linux:644、755、777权限详解(示例代码)

    第一位7等于4+2+1,rwx,所有者具有读取.写入.执行权限: 第二位5等于4+1+0,r-x,同组用户具有读取.执行权限但没有写入权限: 第三位5,同上,也是r-x,其他用户具有读取.执行权限但没 ...

  8. linux less 编码,Linux less命令详解(示例代码)

    less 在Linux下查看文件内容的命令大致有以下几种: cat 由第一行开始显示内容,并将所有内容输出 tac 从最后一行倒序显示内容,并将所有内容输出 more 根据窗口大小,一页一页的现实文件 ...

  9. linux中expr的用法,linux expr命令参数及用法详解(示例代码)

    expr用法 expr命令一般用于整数值,但也可用于字符串.一般格式为: #expr argument operator argument expr也是一个手工命令行计数器. #$expr 10 + ...

  10. linux .. 权限详解,Linux用户及权限详解(示例代码)

    加密方法: 对称加密:加密和解密使用同一个密码 公钥加密:每个密码都成对儿出现,一个为私钥(secret key),一个为公钥(public key) 单向加密,散列加密:提取数据特征码,常用于数据完 ...

最新文章

  1. Google也开始弄开源平台,好事啊
  2. [javaEE] 三层架构案例-用户模块(二)
  3. CH - 0601 Genius ACM(倍增+归并排序)
  4. 在 Excel 中如何使用宏示例删除列表中的重复项
  5. 【C语言重点难点】数据类型、常量和变量
  6. 关于在vSphere环境中,安装WindowsServer2008_R2_x64系统,分区格式为GPT,隐藏分区为200M方法心得
  7. 【学习笔记】OSG 基本几何图元
  8. STC单片机 命名规则,最小系统 图示
  9. 修改mysql的authen_MySQL连接抛出Authentication Failed错误的分析与解决思路
  10. MySQL数据库高级SQL语句【进阶查询、null值、数据库正则、数据库运算符、连接查询(内连接、左外连接、右外连接)】
  11. 成就更好的自己,就是不停地做减法
  12. python 求x的 n次方
  13. 阿迪达斯携手麦当劳推出篮球明星鞋服;拜耳联合导师计划支持中国医药初创企业 | 美通企业日报...
  14. 【Kotlin 初学者】为什么要学Kotlin
  15. Python有趣应用之Python帮你潜伏侦查网聊美女
  16. Wow魔兽世界服务器搭建详细教程,魔兽世界服务器配置要求
  17. 2021-06-26
  18. PS切图工具retinize it actions的用法
  19. 机器学习:有监督算法之分类
  20. 13.Struts2_动态方法调用(了解)

热门文章

  1. c#控件chart制作自动更新的温湿度实时曲线图
  2. win10 如何设置眼睛保护色(绿色)
  3. 七人表决器VHDL代码
  4. 数据中心与灾备中心建设总结
  5. 华硕主板破linux密码破解,华硕P8B75-M-LE老主板加持NVMe SSD bios(刷新软件和bios)...
  6. 吸尘器上亚马逊要求UL1017测试报告怎么办
  7. FreeRtos在RH850 D1L芯片上移植
  8. 概念梳理:C++中iostream头文件和命名空间的基础介绍和拓展内容
  9. VmPlayer上设置主机和windows虚拟机文件夹共享
  10. Xshell 5使用教程