【Linux设备驱动程序(第三版)】----简单休眠 Sleepy
sleepy.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/fs.h>//file_operations, file
#include <linux/completion.h>
#include <asm/uaccess.h>//copy_to_user & copy_from_user
#include <linux/wait.h>
MODULE_LICENSE("Dual BSD/GPL");
#define MEMSIZE 100
int sleepy_major = 250;
DECLARE_COMPLETION(comp);
unsigned char s[MEMSIZE];
static DECLARE_WAIT_QUEUE_HEAD(wq);
static int flag = 0;
ssize_t sleepy_read(struct file *filp, char __user *buf, size_t size, loff_t *pos)
{
unsigned long p = *pos;
unsigned int count = size;
int ret = 0;
if(p >= MEMSIZE)
return 0;
if(count > MEMSIZE - p)
count = MEMSIZE -p;
wait_event_interruptible(wq, flag != 0);
flag = 0;
if(copy_to_user(buf, (void*)(s + p), count)){
return -EFAULT;
}
*pos += count;
ret = count;
return ret;
}
ssize_t sleepy_write(struct file *filp, char __user *buf, size_t size, loff_t *pos)
{
unsigned long p = *pos;
unsigned int count = size;
int ret = 0;
if(p >= MEMSIZE)
return 0;
if(count > MEMSIZE - p)
count = MEMSIZE -p;
if(copy_from_user(s + p, buf, count)){
return -EFAULT;
}
flag = 1;
wake_up_interruptible(&wq);
*pos += count;
ret = count;
complete(&comp);
return ret;
}
struct file_operations sleepy_fops = {
.owner = THIS_MODULE,
.read = sleepy_read,
.write = sleepy_write,
};
int sleepy_init(void)
{
int result;
result = register_chrdev(sleepy_major, "sleepy", &sleepy_fops);
if(result < 0)
return result;
return 0;
}
void sleepy_exit(void)
{
unregister_chrdev(sleepy_major, "sleepy");
}
module_init(sleepy_init);
module_exit(sleepy_exit);
Makefile
obj-m:= sleepy.o
modules-objs:= sleepy.o
KDIR:= /usr/src/linux-headers-2.6.31-14-generic/
PWD:= $(shell pwd)
default:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -rf *.ko *.mod.c *.mod.o *.o *.markers *.symvers *.order
创建设备节点
mknod /dev/sleepy c 250 0
装载
insmod sleepy.ko
打开一终端,输入:
cat /dev/sleepy
此时,线程会进入休眠。
打开另一个终端,输入:
echo "Test" > /dev/sleepy
这个时候,上一个的读线程运行,并输出:“Test”
卸载
rmmod sleepy