Windows XP Windows 7 Windows 2003 Windows Vista Windows教程綜合 Linux 系統教程
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟件教程
 Windows教程網 >> Linux系統教程 >> Linux教程 >> select function and how to use for our driver

select function and how to use for our driver

日期:2017/2/7 14:39:59      編輯:Linux教程
 

select()函數?
select()函數的接口主要是建立在一種叫'fd_set'類型的基礎上。它('fd_set') 是一組文件描述符(fd)的集合。由於fd_set類型的長度在不同平台上不同,因此應該用一組標准的宏定義來處理此類變量:

fd_set set;
FD_ZERO(&set); /* 將set清零 */
FD_SET(fd, &set); /* 將fd加入set */
FD_CLR(fd, &set); /* 將fd從set中清除 */
FD_ISSET(fd, &set); /* 如果fd在set中則真 */

在過去,一個fd_set通常只能包含少於等於32個文件描述符,因為fd_set其實只用了一個int的比特矢量來實現,在大多數情況下,檢查 fd_set能包括任意值的文件描述符是系統的責任,但確定你的fd_set到底能放多少有時你應該檢查/修改宏FD_SETSIZE的值。*這個值是系統相關的*,同時檢查你的系統中的select() 的man手冊。有一些系統對多於1024個文件描述符的支持有問題。[譯者注: Linux就是這樣的系統!你會發現sizeof(fd_set)的結果是128(*8 = FD_SETSIZE=1024) 盡管很少你會遇到這種情況。]

select的基本接口十分簡單:

int select(int nfds, fd_set *readset, fd_set *writeset,
fd_set *exceptset, struct timeval *timeout);

其中:

nfds
需要檢查的文件描述符個數,數值應該比是三組fd_set中最大數
更大,而不是實際文件描述符的總數。
readset
用來檢查可讀性的一組文件描述符。
writeset
用來檢查可寫性的一組文件描述符。
exceptset
用來檢查意外狀態的文件描述符。(注:錯誤並不是意外狀態)
timeout
NULL指針代表無限等待,否則是指向timeval結構的指針,代表最
長等待時間。(如果其中tv_sec和tv_usec都等於0, 則文件描述符
的狀態不被影響,但函數並不掛起)

函數將返回響應操作的對應操作文件描述符的總數,且三組數據均在恰當位置被修改,只有響應操作的那一些沒有修改。接著應該用FD_ISSET宏來查找返回的文件描述符組。

這裡是一個簡單的測試單個文件描述符可讀性的例子:

int isready(int fd)
{
int rc;
fd_set fds;
struct timeval tv;

FD_ZERO(&fds);
FD_SET(fd,&fds);
tv.tv_sec = tv.tv_usec = 0;

rc = select(fd+1, &fds, NULL, NULL, &tv);
if (rc < 0)
return -1;

return FD_ISSET(fd,&fds) ? 1 : 0;
}

當然如果我們把NULL指針作為fd_set傳入的話,這就表示我們對這種操作的發生不感興趣,但select() 還是會等待直到其發生或者超過等待時間。

2, select 函數需要驅動支持,在實現的數據結構file_operations 中有一成員函數poll,驅動程序可通過對其實現已使用select函數。

static struct file_operations fops =
{
ioctl: ioctl,
mmap: mmap,
open: open,
release: release,
poll: poll,
};
u32 wwpoll(struct file *fp, poll_table *wait)
{
u32 cid;
inode = fp->f_dentry->d_inode;

//this functiion wil wait sigal that send by wake_up_interruptible(&ch->pollqueue)
poll_wait(fp, &ch->pollqueue, wait);
if (ch->pollflag) {
ch->pollflag = 0;
if (cid <= WWENC_LAST) {
return (POLLIN|POLLRDNORM);
}
else {
// wwprtk("wwpoll: return POLLOUT from wwpoll for cid=%d\n", cid);
return (POLLOUT|POLLWRNORM);
}
}
return 0;
}

[譯者注:在Linux中,timeout指的是程序在非sleep狀態中度過的時間,而不是實際上過去的時間,這就會引起和非Linux平台移植上的時間不等問題。移植問題還包括在System V風格中select()在函數退出前會把timeout設為未定義的 NULL狀態,而在BSD中則不是這樣,Linux在這點上遵從System V,因此在重復利用timeout指針問題上也應該注意。]
 

Copyright © Windows教程網 All Rights Reserved