在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");