編寫了乙個虛擬的驅動,實現的功能是在讀裝置時阻塞,直到有資料寫入裝置,然後才能讀出寫入的資料。
其中有訊號量的操作與阻塞非阻塞io的操作,
最後寫了乙個應用程式進行驗證
驅動如下:
#include #include #include #include #include #include #include #include /*for spinlock and semaphore*/
#include #include #include /*for task management*/
#include #include #include #define device_name "pcio"
#define driver_name "mypcio"//載入驅動之後會在/dev/目錄下發現mypcio,應用程式可以使用
#define pcio_major 0 //預設的pcio的主裝置號
static int pcio_major = pcio_major;
static int pcioopencount=0;
static int flag=0;
static int global_var = 0;
struct class *pcio_class;
static struct device *pciodevice=null;
static wait_queue_head_t wqueue;
struct pcio_dev
;struct pcio_dev *pcio_devp;//裝置結構體指標
//開啟函式
static int pcio_open(struct inode *inode, struct file *file)
//關閉函式
static int pcio_close(struct inode *inode, struct file *file)
//讀函式
static ssize_t pcio_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
//獲取訊號量
if(down_interruptible(&pcio_devp->sem))
//從核心空間到使用者空間的資料拷貝
if(copy_to_user(buff,&global_var,sizeof(int)) != 0)
/*data unaccessible flag*/
flag = 0;
/*release semaphore*/
up(&pcio_devp->sem);
return sizeof(int);
}//寫函式
static ssize_t pcio_write(struct file *filp, const char __user *buff, size_t count, loff_t *offp)
printk("down_interruptible ok!\n");
if(copy_from_user(&global_var,buff,sizeof(int) != 0))
/*release semaphore*/
up(&pcio_devp->sem);
/*data ready*/
flag = 1;
/*wake up the waiting task*/
wake_up_interruptible(&wqueue);
return sizeof(int);
} //dev_fops操作指令集
static struct file_operations pcio_fops =
; /*//第三步:混雜裝置定義
static struct miscdevice my2416ledmisc =
;*/static void pcio_setup_cdev(struct pcio_dev *dev,int index)
/*驅動模組載入*/
static int pcio_dev_init(void)
else//動態申請裝置號
if(ret<0)
//動態申請裝置結構體內存
pcio_devp=kmalloc(sizeof(struct pcio_dev), gfp_kernel);
if(!pcio_devp)//申請失敗
printk("dev:kmalloc succeed\n");
/*清除空間*/
memset(pcio_devp,0,sizeof(struct pcio_dev));
/*建立乙個裝置*/
pcio_setup_cdev(pcio_devp,0);
//class_create和device_create函式是為了自動在/dev下建立driver_name裝置檔案。
//建立乙個類,這個類存放於sysfs下面
pcio_class=class_create(this_module,driver_name);
if(is_err(pcio_class))
//在/dev目錄下建立相應的裝置節點
pciodevice = device_create(pcio_class,null,devno,null,driver_name);
if(is_err(pciodevice))
//初始化訊號量
sema_init(&pcio_devp->sem,1);
//初始化等待佇列
init_waitqueue_head(&wqueue);
fail_malloc:
unregister_chrdev_region(devno,1);//釋放裝置號
class_create_fail:
unregister_chrdev_region(mkdev(pcio_major, 0), 1);//釋放裝置號
device_create_faile:
class_destroy(pcio_class);/*登出建立的裝置類*/
return ret;
}static void __exit pcio_dev_exit(void)
module_init(pcio_dev_init);
module_exit(pcio_dev_exit);
module_author("zhao yidong ");
module_license("dual bsd/gpl");
module_description("a sampleio module");
module_alias("a sample module");
相應的makefile檔案如下:
#makefile for pciomodule.c.c
#arch=arm
#cross_compile=arm-linux-gnueabihf-
ifneq ($(kernelrelease),)
obj-m := pciomodule.o
else
#bbblack kernel
#kerneldir ?= /usr/local/ti-sdk-beagleboard/board-support/linux-3.3.7
#pc kernel
kerneldir ?=/lib/modules/$(shell uname -r)/build
pwd := $(shell pwd)
modules:
$(make) -c $(kerneldir) m=$(pwd) modules
modules_install:
$(make) -c $(kerneldir) m=$(pwd) modules_install
clean:
$(make) -c $(kerneldir) m=$(pwd) clean
endif
測試的應用程式如下:
#include #include #include #include #include #include #include /*
*/int main(int argc, char** args)
}//while
} else
} else if (strcmp(args[1], "1") == 0)
}} else }}
return 0;
}
最後開啟兩個終端,執行測試程式如下圖,每次在寫終端寫入乙個數,在讀取程式終端就會看到寫入的資料。
嵌入式linux getchar 非阻塞
由於getchar 函式會一直阻塞,網上搜到下面的函式來實現非阻塞的讀取。實際使用的時候只需要呼叫kbhit 函式即可。其他函式沒有看是什麼意思 include include include include include include include static struct termios...
Linux阻塞與非阻塞
1.阻塞 block 概念 指程序或執行緒在執行裝置操作或管道,或則網路時,不能獲取到資源就被掛起,直到滿足可操作的條件後在進行操作,被掛起的程序進入休眠狀態,從執行佇列移走,直到 等待的條件滿足才繼續執行。也就是執行到某些函式時必須等待某個事件發生函式才返回。2.非阻塞 non block 程序就...
阻塞式 非阻塞式IO
知識點 非阻塞式io 的兩種設定方法 1 函式fcntl 設定 o nonblock 選項 int flag fcntl sockfd,f getfl,0 檢查檔案標誌位 fcntl sockfd,f setfl,flag o nonblock 設定檔案標誌位 2 函式ioctl 設定fionbio...