linux设备驱动--等待队列实现

时间:2022-08-27 07:54:19
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include "ioctl_led.h"

#define DEV_NAME"test-dev"
volatile bool empty = true;
//定义一个进程资源的指针变量
struct task_struct *task;

int test_open(struct inode *inode, struct file *filp)
{
printk("test open\n");
return 0;
}

int test_close(struct inode *inode, struct file *filp)
{
printk("test close\n");
return 0;
}

ssize_t test_read(struct file *filp, char __user *buf, size_t size, loff_t *off)
{
int ret;
//如果为真,那么就开始读
while(empty)
{
//f_flags 指的是对应open调用的时候所指定的flag
//O_NONBLOCK 非阻塞形式打开
if(filp->f_flags & O_NONBLOCK)
{
return 0;
}
//current(指向当前进程的task_struct)
//(内核栈的底部thread_info.task)
task = current;
//设置当前进程的状态为TASK_INTERRUPTIBLE
//TASK_INTERRUPTIBLE是阻塞态,进程当前正在等待除CPU外的其他系统资源,可以被信号唤醒.
set_current_state(TASK_INTERRUPTIBLE);
//通知调度器执行调度。
schedule();
if(signal_pending(current))
return -ERESTARTSYS;
//return -EAGAIN;

printk("read: wake up\n");
}

ret = size;
empty = true;
return ret;
}

ssize_t test_write(struct file *filp, const char __user *buf, size_t size, loff_t *off)
{
int ret;

empty = false;
wake_up_process(task);
ret = size;

return ret;
}

int major = 0;
struct file_operations fops = {
.open = test_open,
.release = test_close,
.read = test_read,
.write = test_write,
};

//模块;
int test_init(void)
{
int ret;
printk("test init\n");
//注册一个字符设备驱动
ret = register_chrdev(major, DEV_NAME, &fops);
if(ret < 0)
return ret;
else
{
if(0 == major)
{
major = ret;
printk("major = %d\n", major);
}
}

return 0;
}

void test_exit(void)
{
printk("test exit\n");
//撤销字符设备
unregister_chrdev(major, DEV_NAME);
}

module_init(test_init);
module_exit(test_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("yang.yx");
MODULE_VERSION("1.1");

Makefile

obj-m+= test.o

ROOTFS = /rootfs
KERNEL_SRC= /lib/modules/`uname -r`/build

all:
make -C $(KERNEL_SRC) M=`pwd` modules

clean:
make -C $(KERNEL_SRC) M=`pwd` clean
rm -rf app

install:
make -C $(KERNEL_SRC) M=`pwd` modules_install INSTALL_MOD_PATH=$(ROOTFS)

app:
arm-linux-gcc app.c -o app
ioctl.c

#ifndef__IOCTL_H__
#define __IOCTL_H__

#include <linux/ioctl.h>

#define LED_TYPE0x1

#define LED_ALLON_IO(LED_TYPE, 0)
#define LED_ALLOFF_IO(LED_TYPE, 1)
#define LED_ON_IOW(LED_TYPE, 2, int)
#define LED_OFF_IOW(LED_TYPE, 3, int)

#endif