字符设备驱动
来源:互联网 发布:单身约会软件app 编辑:程序博客网 时间:2024/06/06 09:13
使用原子锁实现设备只能被一个进程打开
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/cdev.h>
- #include <linux/errno.h>
- #include <linux/mm.h>
- #include <linux/types.h>
- #include <linux/sched.h>
- #include <linux/fs.h>
- #include <asm/io.h>
- #include <linux/slab.h>
- #include <asm/uaccess.h>
- #define GLOBAL_MAJOR 0
- #define GLOBAL_MAXMEM 0x1000
- #define DEV_NAME ("globalmem")
- int globalmem_major = GLOBAL_MAJOR;
- static atomic_t my_available = ATOMIC_INIT(1);
- struct globalmem_dev{
- struct cdev cdev;
- unsigned char mem[GLOBAL_MAXMEM];
- };
- struct globalmem_dev *globalmem_devp;
- static int globalmem_open(struct inode *inode, struct file *filp)
- {
- if(!atomic_dec_and_test(&my_available))
- {
- atomic_inc(&my_available);
- return -EBUSY;
- }
- filp->private_data = globalmem_devp;
- return 0;
- }
- static int globalmem_release(struct inode *inode, struct file *filp)
- {
- atomic_inc(&my_available);
- return 0;
- }
- static ssize_t globalmem_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
- {
- unsigned long p = *ppos;
- unsigned int count = size;
- int ret = 0;
- struct globalmem_dev *dev = filp->private_data;
- if(p >= GLOBAL_MAXMEM)
- return 0;
- if(count + p > GLOBAL_MAXMEM)
- count = GLOBAL_MAXMEM - p;
- if(copy_to_user(buf, (void*)dev->mem, count))
- {
- return -EFAULT;
- }
- else
- {
- *ppos += count;
- ret = count;
- }
- return ret;
- }
- static ssize_t globalmem_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)
- {
- unsigned long p = *ppos;
- unsigned int count = size;
- int ret = 0;
- struct globalmem_dev *dev = filp->private_data;
- if(p > GLOBAL_MAXMEM)
- return 0;
- if(count + p > GLOBAL_MAXMEM)
- count = GLOBAL_MAXMEM - p;
- if(copy_from_user(dev->mem, buf, count))
- {
- return -EFAULT;
- }
- else
- {
- *ppos += count;
- ret = count;
- }
- return ret;
- }
- static const struct file_operations globalmem_ops = {
- .owner = THIS_MODULE,
- .open = globalmem_open,
- .read = globalmem_read,
- .write = globalmem_write,
- .release = globalmem_release,
- };
- static void globalmem_setup(struct globalmem_dev *dev, int index)
- {
- int err, devno = MKDEV(globalmem_major, index);
- cdev_init(&dev->cdev, &globalmem_ops);
- dev->cdev.owner = THIS_MODULE;
- err = cdev_add(&dev->cdev, devno, 1);
- if(err)
- printk(KERN_ERR "### cdev_add fail \n");
- }
- static int __init globalmem_init(void)
- {
- int res;
- dev_t devno = MKDEV(globalmem_major, 0);
- if(globalmem_major)
- res = register_chrdev_region(devno, 1, DEV_NAME);
- else
- {
- res = alloc_chrdev_region(&devno, 0, 1, DEV_NAME);
- globalmem_major = MAJOR(devno);
- }
- if(res < 0)
- return res;
- globalmem_devp = kmalloc(sizeof(struct globalmem_dev), GFP_KERNEL);
- if(!globalmem_devp)
- {
- res = -ENOMEM;
- goto fail_malloc;
- }
- memset(globalmem_devp, 0, sizeof(struct globalmem_dev));
- globalmem_setup(globalmem_devp, 0);
- return 0;
- fail_malloc:
- unregister_chrdev_region(devno, 1);
- return res;
- }
- static void __exit globalmem_exit(void)
- {
- cdev_del(&globalmem_devp->cdev);
- kfree(globalmem_devp);
- unregister_chrdev_region(MKDEV(globalmem_major, 0), 1);
- }
- MODULE_LICENSE("GPL");
- module_init(globalmem_init);
- module_exit(globalmem_exit);
Makefile
- obj-m := globalmem_dev.o
- globalmem_dev-objs := dev_globalmem.o
- KID :=/lib/modules/`uname -r`/build
- PWD := ${shell pwd}
- defalt:
- make -C $(KID) M=${PWD} modules
- clean:
- rm -rf *.o *.cmd *.ko *.mod.c *.tmp_versions *.order *.symvers .*.*.cmd
测试程序:
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <fcntl.h>
- #define NODE_NAME ("/dev/globalmem")
- #define TO_WRITE "664"
- #define BUF_LENGTH 128
- int main()
- {
- int filp, filp2;
- int res = 0;
- char buf[BUF_LENGTH];
- memset(buf, 0, BUF_LENGTH);
- filp = open(NODE_NAME, O_RDWR);
- if(filp > 0)
- {
- if( (res = read(filp, buf, BUF_LENGTH) ) < 0)
- printf("read error \n");
- else
- {
- printf("first read is %s\n", buf);
- }
- if((res = write(filp, TO_WRITE, strlen(TO_WRITE))) != strlen(TO_WRITE))
- printf("write error \n");
- close(filp);
- filp = open(NODE_NAME, O_RDWR);
- memset(buf, 0, BUF_LENGTH);
- if( (res = read(filp, buf, BUF_LENGTH) ) < 0)
- printf("read error \n");
- else
- {
- printf("second read is %s\n", buf);
- }
- }
- else
- {
- printf("open file fail \n");
- }
- while(1);
- close(filp);
- exit(0);
- }
4. 验证效果
1) make
2) insmod scull.ko
3) cat /proc/devices | grep scull //获取字符设备scull的主设备号,我的是248
4) cd /dev/
5) mknod scull c 248 0
编译 测试程序
cc -o test test.c
运行
成功锁住。
0 0
- 字符设备驱动--- 设备操作
- 字符设备驱动更新
- 字符设备驱动模板
- 字符设备驱动模板
- 字符设备驱动1
- 字符设备驱动编写
- LINUX--字符设备驱动
- 字符设备驱动01
- 字符设备驱动02
- LED字符设备驱动
- led字符设备驱动
- Linux字符设备驱动
- 字符设备驱动
- Linux字符设备驱动
- Linux字符设备驱动
- 字符设备驱动分析
- 字符设备驱动详解
- 字符设备驱动实验
- js判断变量是否空值的代码
- The following signatures couldn't be verified because the public key is not available
- ClassLoader理解
- HDOJ1021 Fibonacci Again
- 关于alibaba的fastjson
- 字符设备驱动
- linux版本 Centos下安装tar包/rpm包
- VS2008项目中相关目录的说明
- RT_Thread最新开发板RealBoard—LPC4088的介绍及编译环境的搭建和下载
- 树莓派(rasperberry pi 2)上装mysql远程无法访问
- java23种设计模式--装饰模式(decorator)
- Windows 7-64位安装PLSQL-Developer
- java compiler level does not match the version of the installed java project facet
- ajax的data传参的两种方式