29 mutex互斥锁

在linux内核里用struct task_struct 的一个对象描述一个进程和线程:

#include <linux/sched.h>
struct task_struct {
    ...
    volatile long state;    /*其实进程线程是否休眠就是改变这个状态 -1 unrunnable, 0 runnable, >0 stopped */

    pid_t pid; //进程号
    char comm[TASK_COMM_LEN]; //进程对应的程序名
};

#include <asm/current.h>
#define current (get_current()) //在驱动源码里可通过这个宏获取当前调用的用户进程的task_struct对象地址
current->pid; //获取当前调用我们驱动功能函数的进程的进程号
current->comm; //可获取当前调驱动功能函数的进程的程序名.

//

我们实现的驱动功能函数是给用户进程来调用的,驱动本身是不休眠,只能是调用的进程或线程才可以休眠.
我们可以在驱动源码里安排条件不满足执行的进程或线程体眠,直到条件满足才接着执行。
用锁就可以实现这种功能.

在miscdevice的封装层的代码里有使用到mutex互斥锁保护对misc_list链表的操作.

#include <linux/mutex.h>
struct mutex互斥锁.只有两种状态, 可锁上/锁不上.不管解锁多少次也只能锁上一次.
    当锁不上时,调用的进程或线程就会被安排进入休眠状态,直到解锁为止.

void mutex_init(struct mutex *mutex); //初始化锁.注意初始化后,锁是可锁上一次的
void mutex_lock(struct mutex *lock); //上锁。如锁不上,则调用的进程或线程进入不可中断(不被信号唤醒)的休眠
int __must_check mutex_lock_interruptible(struct mutex *lock); //上锁,如锁不上,则调用进程或线程进入可中断的休眠.
int mutex_trylock(struct mutex *lock); //尝试锁。不管锁上还是锁不上都会让进程或线程进入休眠.要通过返回值来判断是否已锁上.

void mutex_unlock(struct mutex *lock); //解锁

//
如实现当用户进程来读数据时,如果没有数据可读时安排进程进入休眠,直到另一个进程写入数据.

test.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/atomic.h>
#include <linux/sched.h>
#include <asm/current.h>
#include <linux/mutex.h>
#include <asm/uaccess.h>

struct mutex mymutex;
char data[200];
ssize_t myread(struct file *fl, char __user *buf, size_t len, loff_t *off)
{
    int ret;

    ret = mutex_lock_interruptible(&mymutex);
    if (ret < 0)
        return -ERESTART; //被信号唤醒时的处理

    printk("pid = %d, %s:", current->pid, current->comm);   
    ret = copy_to_user(buf, data, strlen(data));

    return strlen(data)-ret;
}

ssize_t mywrite(struct file *fl, const char __user *buf, size_t len, loff_t *off)
{
    int ret;

    ret = copy_from_user(data, buf, len);
    mutex_unlock(&mymutex); //有进程写入数据后,解锁
    return len-ret;
}

struct file_operations fops = {
    .owner = THIS_MODULE,
    .read = myread,
    .write = mywrite,
};

struct miscdevice mymdev = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = "mymdev",
    .fops = &fops,
};

static int __init test_init(void)
{
    mutex_init(&mymutex); //初始化互斥锁
    mutex_lock(&mymutex); //初始化后,锁是可锁的。这里锁上是确保用户进程读数据时会进入休眠
    return misc_register(&mymdev);
}

static void __exit test_exit(void)
{
    misc_deregister(&mymdev);
}

module_init(test_init);
module_exit(test_exit);

MODULE_LICENSE("GPL");
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值