參考:
linux裝置驅動開發詳解:基於最新的linux4.0核心:宋寶華編著.
程式設計離不開資料, 所以資料獲取是程式設計的第一步.
資料io可以是阻塞式式的或非阻塞式的.
例如讀取資料,當資料沒有準備好時,是把讀取執行緒或程序阻塞,還是立即返回乙個無資料的錯誤. 這可由使用者選擇.
預設的檔案開啟方式是阻塞式讀寫. 如果想非阻塞式讀寫,需要如此開啟檔案:
int fd = open(path,o_rdonly | o_nonblock)
這個path 可能是個裝置檔案,例如:/dev/globalfifo
這個open操作將會呼叫到驅動中的globalfifo_open(struct inode *inode, struct file *filp);
開啟的屬性(o_rdonly | o_nonblock) 會保留在filp->f_flags中
filp 是系統提供的乙個檔案結構指標, 開啟操作只需要把你的私有資料掛到filp->private_data
filp->private_data = globalfifo_devp;
inode 對應乙個檔案節點,這裡沒有用到,先不管它.
例如:read(fd,buf,5);
將會呼叫到驅動的read 函式
ssize_t globalfifo_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
傳來的引數包括那個特定的filp 指標, 從這可以拿到源資料資訊.
還有使用者空間的位址和大小. 向這個地方copy
最後1個引數ppos, 是位置偏移指標, 從這裡(*ppos)=offset 可以拿到位址偏移.
所以當使用者讀走了count 個資料,為了保證下次繼續讀新資料,你需要把偏移更正一下.
*ppos += count;
seek 函式能夠直接改變檔案的讀寫指標, 他是如何使用的?
off_t lseek(int fd, off_t offset, int whence);
對應於驅動的
static loff_t globalfifo_llseek(struct file *filp, loff_t offset, int orig)
這個偏移值offset, 會被儲存到filp->pos 處
從開始處偏移 filp->f_pos = (unsigned int)offset; 或者從現在處偏移
filp->f_pos += offset;
這樣使用者讀取時能被正確的傳遞偏移
驅動中的讀函式,當資料不可讀時,如果是o_nonblock 模式,應立即返回
while (dev->current_len == 0)
}
否則需要掛起執行的程序,當資源可用時再喚醒.
掛起很簡單,呼叫
__set_current_state(task_interruptible); //也允許訊號喚醒
schedule();
即可.如何喚醒? 這需要把當前程序加到乙個等待佇列中
declare_waitqueue(wait, current);
add_wait_queue(&dev->r_wait, &wait);
當有資料寫入時,喚醒這個等待佇列
wake_up_interruptible(&dev->r_wait);
我們都知道著名的select 函式
select(fd + 1, &rfds, &wfds, null, null);
它能同時監視讀,寫描述符集, 有乙個有效即被喚醒. 它是如何實現的?
原來select 函式會呼叫驅動的poll 函式,每乙個監控的fd的poll都會呼叫.
static unsigned int globalfifo_poll(struct file *filp, poll_table * wait)
它傳來乙個poll_table* wait, 應該有程序的資訊.
poll_wait(filp, &dev->r_wait, wait);
poll_wait(filp, &dev->w_wait, wait);
驅動把這個wait 加入到等待佇列中, 以後如果資源可用時,會喚醒這個等待佇列,從而
select 能夠從阻塞中繼續執行.
驅動的poll函式並不會阻塞,它加入等待佇列後,返回自己的狀態就可以了.
if (dev->current_len != 0)
if (dev->current_len != globalfifo_size)
return mask;
這會置位fdset 的對應bit, 使使用者知道哪個fd 置位了.
int fd = open("/dev/globalfifo", o_rdwr, s_irusr | s_iwusr); //開啟乙個檔案
signal(sigio, signalio_handler); //註冊乙個sigio 訊號處理器
fcntl(fd, f_setown, getpid()); // 設定本fd為非同步io, 第一步,設定current pid
int oflags = fcntl(fd, f_getfl);
fcntl(fd, f_setfl, oflags | fasync); // 設定為非同步標記
while (1)
當然,要支援非同步操作,驅動也要做相應修改. 主要是當資料可讀時,從驅動向呼叫者發sigio訊號
Java基礎 檔案資料IO操作
檔案資料io操作 1.1.字元流原理 reader是所有字元輸入流的父類而writer是所有字元輸出流的父類。字元流是以字元 char 為單位讀寫資料的。一次處理乙個unicode。字元流都是高階流,其底層都是依靠位元組流進行讀寫資料的,所以底層仍然是基於位元組讀寫資料的。1.2.常用方法 read...
Python資料分析筆記 檔案資料讀取
讀取檔案內容首行 path c users etisan desktop a.txt open path readline 注 檔案路徑要用雙反斜槓 第乙個 的作用是轉義字元 讀取檔案內容某一行 records line for line in open path records 1 匯入json,...
DBF檔案資料結構例項分析
dbf檔案資料結構例項分析下面以乙個具體例項來分析dbf資料結構 該 資料為 列1 列21 2 2 43 6 4 85 10 6 12 7 14 8 16 9 18 10 20 用ultraedit開啟該dbf檔案,其內容如下 現在先分解一下,找出檔案頭,並分析一下檔案頭的內容。首先看第乙個位元組,...