#include#include #include #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#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