先悔過一下。因為一個月前就在學習這個,當時解決的差不多了,想著抽個空再記錄這些,沒想到這麼短的時間就已經忘得
差不多了,真是不好,應該趁熱打鐵。廢話不多說了,這裡主要介紹在Linux下,利用訊號來實現非同步串口中斷響應。主要思路
很簡單,首先是關聯訊號,在此是關聯處理SIGPOLL;其次是等待指定的訊號。
非同步I/O的實現有很多方式,【2】中提了幾種,還有較新的epoll,和Poll本質上差不多。但本人當時尚不理解這些,沒有明
白select、Poll等的具體做法,也採用了多線程。其實萬萬不該,由於邏輯處理的不好而導致的程式不可預測性太多,因此不太
同意【2】中的觀點,只是用來參考使用了。但我這裡講的做法也是在多線程條件下的非同步串口通訊。
Linux下訊號的概念、原理以及初步的應用【1】中的上、下已經講解得非常到位了,仔細讀讀都能找到自己所需要的。下面
具體記錄我的實現過程。
(1)關聯訊號。
首先是利用sigaction函數來將指定的訊號與處理函數關聯,以及通過fcntl函數確定是在哪個線程中,關聯哪個裝置檔案。
那麼先是sigaction函數的原型:int sigaction(int signum,const struct sigaction *act ,struct sigaction *oldact);
其中struct sigaction 中的內容意義可以看【3】,
struct sigaction sact;
sigemptyset(&sact.sa_mask); //一般都先清空關注的訊號集
sact.sa_flags=SA_SIGINFO; //訊號的附加資訊傳遞開關,可以在訊號SIGIO上傳遞附加資訊,其實就是
//區別POLL_IN,POLL_OUT,為什麼要使用附加資訊,自己試試SIGIO訊號就知道了,它是讀寫不加區分的
sact.sa_sigaction=signal_action; //訊號處理函數,由於利用了訊號附加資訊,函數原型為
//void handler(int signum,siginfo_t *info,void *context);關鍵是siginfo_t結構體中的si_code,其中儲存了POLL_IN等。
//到時候利用info->si_code== POLL_IN或POLL_OUT在串口有讀或寫時做相應的處理
好了,利用sigaction(SIGPOLL,&sact,NULL);完成訊號關聯;再通過下面的操作完成指定的裝置檔案、線程
fcntl(fd, F_SETOWN, tid); //tid就是擷取的線程號,嵌入式環境下可以使用syscall(SYS_gettid);
fcntl(fd, F_SETSIG,SIGPOLL ); //關心SIGPOLL訊號
fcntl(fd,F_SETFL,O_ASYNC|O_NONBLOCK); //非同步
(2)等待訊號
其實按照上面的做法,完全可以達到當串口有指定資料時進行相應的處理,只要指定的線程在,訊號處理函數將會一直起
作用。另一種做法是在接收線程等待訊號的發生,而後做相應的處理,自認為雙保險,其實很混亂,只是記下來。注意的是在信
號等待或者屏蔽函數中要區分是對線程起作用的還是作用在進程上的。【1】中和【6】中說了很多,我這裡只是用到了線上程中
等待訊號傳遞過來的函數sigwaitinfo(),要是想加上時間限制也可以使用sigtimedwait();函數原型:
int sigwaitinfo(const sigset_t *set,siginfo_t *info);按照man中的說法只有當你指定的訊號(在參數set訊號集中)被傳遞到使用這個函數的線程時,該函數返回,並將訊號的資訊儲存到後面的info中,也可以供你使用。
(3)嵌入式環境下,在編譯的時候會遇到【4】中的莫名奇妙的問題,其實加上編譯開關選項即可-D_GNU_SOURCE,原因麼自己看【5】了。
好了,就這麼多了,其實啥也沒說,只是把一些可能用到的提了下,跟著路線走,應該能找到自己需要的了。寫得太爛了,誰叫給忘得差不多了!@@@
學習參考文獻:
【1】http://www.ibm.com/developerworks/cn/linux/l-ipc/part2/index1.html
【2】http://blog.csdn.net/boldeagle/archive/2008/10/18/3095930.aspx
【3】http://baike.baidu.com/view/1748537.htm
【4】http://bbs.chinaunix.net/thread-1731238-1-1.html
【5】http://hi.chinaunix.net/?uid-483016-action-viewspace-itemid-42665
【6】《Unix環境進階編程》