嵌入式学习之Linux驱动 信号量

嵌入式Linux驱动之信号量学习

信号量的引入

信号的工作方式

信号量的描述

信号量的API函数

信号量的注意事项

#include <linux/module.h>
#include <linux/init.h>
#include <linux/moduleparam.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/device.h>  

#include <linux/atomic.h>  
#include <asm/atomic.h>  


struct device_test {
    dev_t dev_num;
    int major;
    int minor;
    int flag;

    struct cdev cdev_test;
    struct class *class;
    struct device *device;
    char lbuf[32];
};

struct device_test dev1;
static struct semaphore semlock;    



static int cdev_test_open(struct inode *inode, struct file *file) {

    #if 0
    down(&dev1.cdev_test);
    #endif

    if(down_interruptible(&semlock)){

        return -EINTR;
    }
    file->private_data = container_of(inode->i_cdev, struct device_test, cdev_test);
    printk("This is cdev_test_open\n");
    return 0;
}

static ssize_t cdev_test_read(struct file *file, char __user *buf, size_t size, loff_t *off) {
    struct device_test *test_dev = (struct device_test *)file->private_data;

    if (copy_to_user(buf, test_dev->lbuf, strlen(test_dev->lbuf)) != 0) {
        printk("copy_to_user error\n");
        return -EFAULT;
    }

    return strlen(test_dev->lbuf);
}

static ssize_t cdev_test_write(struct file *file, const char __user *buf, size_t size, loff_t *off) {
    struct device_test *test_dev = (struct device_test *)file->private_data;

    if (size >= sizeof(test_dev->lbuf)) {
        printk("write size too large\n");
        return -EINVAL;
    }

    if (copy_from_user(test_dev->lbuf, buf, size) != 0) {
        printk("copy_from_user error\n");
        return -EFAULT;
    }

    test_dev->lbuf[size] = '\0'; 
    printk("test_dev->lbuf is %s\n", test_dev->lbuf);

    return size;
}

static int cdev_test_release(struct inode *inode, struct file *file) {

    up(&semlock);       //释放信号量,使得其他等待的进程可以继续执行。
    return 0;
}

static struct file_operations cdev_test_ops = {
    .owner = THIS_MODULE,
    .open = cdev_test_open,
    .read = cdev_test_read,
    .write = cdev_test_write,
    .release = cdev_test_release,
};

static int __init modulecdev_init(void) {
    
    int ret;

    sema_init(&semlock, 1);                 //表示这是一个 二进制信号量,即类似于互斥锁(mutex),最多允许一个线程进入临界区。
    ret = alloc_chrdev_region(&dev1.dev_num, 0, 1, "WLD");
    if (ret < 0) {
        printk("alloc_chrdev_region failed\n");
        goto err_chrdev;
    }

    dev1.major = MAJOR(dev1.dev_num);
    dev1.minor = MINOR(dev1.dev_num);
    printk("register_chrdev_region is ok\n");
    printk("major is %d\n", dev1.major);
    printk("minor is %d\n", dev1.minor);

    cdev_init(&dev1.cdev_test, &cdev_test_ops);
    dev1.cdev_test.owner = THIS_MODULE;

    ret = cdev_add(&dev1.cdev_test, dev1.dev_num, 1);
    if (ret < 0) {
        printk("cdev_add failed\n");
        goto err_chr_add;
    }

    dev1.class = class_create(THIS_MODULE, "test");
    if (IS_ERR(dev1.class)) {
        ret = PTR_ERR(dev1.class);
        printk("class_create failed\n");
        goto err_class_create;
    }

    dev1.device = device_create(dev1.class, NULL, dev1.dev_num, NULL, "test1");
    if (IS_ERR(dev1.device)) {
        ret = PTR_ERR(dev1.device);
        printk("device_create failed\n");
        goto err_device_create;
    }

    return 0;

err_device_create:
    class_destroy(dev1.class);
err_class_create:
    cdev_del(&dev1.cdev_test);
err_chr_add:
    unregister_chrdev_region(dev1.dev_num, 1);
err_chrdev:
    return ret;
}

static void __exit modulecdev_exit(void) {
    device_destroy(dev1.class, dev1.dev_num);
    class_destroy(dev1.class);
    cdev_del(&dev1.cdev_test);
    unregister_chrdev_region(dev1.dev_num, 1);

    printk("bye bye\n");
}

module_init(modulecdev_init);
module_exit(modulecdev_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("FASHI");
MODULE_VERSION("V1.0");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值