#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 appioctl.c
#ifndef __IOCTL_H__ #define __IOCTL_H__ #include <linux/ioctl.h> #define LED_TYPE 0x1 #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