您的位置:首页 > 其它

设备驱动-----并发控制--原子操作

2013-07-08 22:52 429 查看
使用原子锁实现设备只能被一个进程打开

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


编译 测试程序

cc -o test test.c

运行







成功锁住。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: