⑴ 學嵌入式linux需要先學什麼
剛入門的時候,淘寶買一塊cortex m3開發板即可入手,通過項目,你需要了解:任務調度、進程間通信、內存管理、設備驅動、文件系統、TCP/IP協議棧、同步非同步、中斷、軟體架構插件化等等基本原理,這些對你後面轉Linux應用開發,安卓開發,後台開發大有好處。
到這一步,就看自己職業方向想往哪裡發展,如果是想深入IOT物聯網做端雲連接,那麼可以把幾種基本匯流排驅動,I2C、SPI、USART理解透,如果是想擁抱互聯網轉入應用開發,那麼可以把基礎組件,如協議棧、文件系統吃透,BAT面試不是很難,問的都是這些基礎。
順便說一下,學東西就要學對市場有用的,不要過於學習屠龍之術,炫技給個人帶來不了財富,公司需要的是能幹活的人。
不準備講過於偏硬體的知識如Cortex-M3的多種中斷模式,操作寄存器組,晶元降噪等內容,而是專注於操作系統基本知識和項目經驗,這些對於開發者後面接觸Linux系統大有脾益,這些軟體開發經驗也是去互聯網公司看重的能力。如有需要學習Linux命令請如下查找:
⑵ ioctl()函數的參數和作用
因為用戶層定義它是個變參函數
ioctl (int __fd, unsigned long int __request, ...)
跟printf似的
⑶ 在設Linux在設備驅動和應用程序的非同步通知交互中,在設備驅動程序中增加信號釋放的作用是
在設備驅動和應用程序的非同步通知交互中,僅僅在應用程序端捕獲信號是不夠的,因為信號的源頭在設備驅動端。因此,應該在合適的時機讓設備驅動釋放信號,在設備驅動程序中增加信號釋放的相關代碼。為了使設備支持非同步通知機制,驅動程序中涉及3項工作。
1)支持F_SETOWN命令,能在這個控制命令處理中設置filp->f_owner為對應進程ID。不過此項工作已由內核完成,設備驅動無須處理。
2)支持F_SETFL命令的處理,每當FASYNC標志改變時,驅動程序中的fasync()函數將得以執行。因此,驅動中應該實現fasync()函數。
3)在設備資源可獲得時,調用kill_fasync()函數激發相應的信號。
驅動中的上述3項工作和應用程序中的3項工作是一一對應的,設備驅動中非同步通知編程比較簡單,主要用到一項數據結構和兩個函數。數據結構是fasync_struct結構體,兩個函數分別是:
1)處理FASYNC標志變更的函數。
int fasync_helper(int fd, struct file *filp, int mode, struct fasync_struct **fa);
2)釋放信號用的函數。
void kill_fasync(struct fasync_struct **fa, int sig, int band);
和其他的設備驅動一樣,將fasync_struct結構體指針放在設備結構體中仍然是最佳選擇。
在設備驅動的fasync()函數中,只需要簡單地將該函數的3個參數以及fasync_struct結構體指針的指針作為第4個參數傳入fasync_helper()函數即可。
在設備資源可以獲得時,應該調用kill_fasync()釋放SIGIO信號。在可讀時,第3個參數設置為POLL_IN,在可寫時,第3個參數設置為POLL_OUT。
⑷ linux非同步IO怎麼理解
就是IO不阻塞即使沒有數據可讀,或者空間可寫時。非同步IO都返回,不管如何情況。簡單點的意思就是進程不會阻塞在你讀寫調用非同步IO系統調用的時候。所以你的執行流可以去做其它的事情,當你確實要確認數據讀寫成功的時候,你在用aio_return這個函數去判斷讀寫成功了嗎。如果你想耗費cpu那你就一值調用aio_return輪詢結果。如果想睡眠等待讀寫完成,那麼你調用aio_suspend這個函數,你就會睡眠,當讀寫完成時,內核會發信號給你,這時,就會執行信號處理函數,並喚醒此進程。要充分理解非同步IO,最好把信號和非同步通知一起搞懂。如果會寫驅動的話,最好自己去實現IO的這些功能,比如阻塞IO,非阻塞IO,輪詢,非同步通知,非同步IO等等,其中又涉及到並發和競爭的問題。
⑸ 當linux應用程序中存在多個非同步通知時怎樣處理
驅動程序運行在內核空間中,應用程序運行在用戶空間中,兩者是不能直接通信的。但在實際應用中,在設備已經准備好的時候,我們希望通知用戶程序設備已經ok,用戶程序可以讀取了,這樣應用程序就不需要一直查詢該設備的狀態,從而節約了資源,這就是非同步通知。好,那下一個問題就來了,這個過程如何實現呢?簡單,兩方面的工作。
一 驅動方面:
1. 在設備抽象的數據結構中增加一個struct fasync_struct的指針
2. 實現設備操作中的fasync函數,這個函數很簡單,其主體就是調用內核的fasync_helper函數。
3. 在需要向用戶空間通知的地方(例如中斷中)調用內核的kill_fasync函數。
4. 在驅動的release方法中調用前面定義的fasync函數
呵呵,簡單吧,就三點。其中fasync_helper和kill_fasync都是內核函數,我們只需要調用就可以了。在
1中定義的指針是一個重要參數,fasync_helper和kill_fasync會使用這個參數。
二 應用層方面
1. 利用signal或者sigaction設置SIGIO信號的處理函數
2. fcntl的F_SETOWN指令設置當前進程為設備文件owner
3. fcntl的F_SETFL指令設置FASYNC標志
完成了以上的工作的話,當內核執行到kill_fasync函數,用戶空間SIGIO函數的處理函數就會被調用了。
呵呵,看起來不是很復雜把,讓我們結合具體代碼看看就更明白了。
先從應用層代碼開始吧:
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#define MAX_LEN 100
//處理函數,沒什麼好講的,用戶自己定義
void input_handler(int num)
{
char data[MAX_LEN];
int len;
//讀取並輸出STDIN_FILENO上的輸入
len = read(STDIN_FILENO, &data, MAX_LEN);
data[len] = 0;
printf("input available:%s\n", data);
}
void main()
{
int oflags;
//啟動信號驅動機制,將SIGIO信號同input_handler函數關聯起來,一旦產生SIGIO信號,就會執行input_handler
signal(SIGIO, input_handler);
//STDIN_FILENO是打開的設備文件描述符,F_SETOWN用來決定操作是干什麼的,getpid()是個系統調用,
//功能是返回當前進程的進程號,整個函數的功能是STDIN_FILENO設置這個設備文件的擁有者為當前進程。
fcntl(STDIN_FILENO, F_SETOWN, getpid());
//得到打開文件描述符的狀態
oflags = fcntl(STDIN_FILENO, F_GETFL);
//設置文件描述符的狀態為oflags | FASYNC屬性,一旦文件描述符被設置成具有FASYNC屬性的狀態,
//也就是將設備文件切換到非同步操作模式。這時系統就會自動調用驅動程序的fasync方法。
fcntl(STDIN_FILENO, F_SETFL, oflags | FASYNC);
//最後進入一個死循環,程序什麼都不幹了,只有信號能激發input_handler的運行
//如果程序中沒有這個死循環,會立即執行完畢
while (1);
}
再看驅動層代碼,驅動層其他部分代碼不變,就是增加了一個fasync方法的實現以及一些改動
//首先是定義一個結構體,其實這個結構體存放的是一個列表,這個
//列表保存的是一系列設備文件,SIGIO信號就發送到這些設備上
static struct fasync_struct *fasync_queue;
//fasync方法的實現
static int my_fasync(int fd, struct file * filp, int on)
{
int retval;
//將該設備登記到fasync_queue隊列中去
retval=fasync_helper(fd,filp,on,&fasync_queue);
if(retval<0)
{
return retval;
}
return 0;
}
在驅動的release方法中我們再調用my_fasync方法
int my_release(struct inode *inode, struct file *filp)
{
//..processing..
drm_fasync(-1, filp, 0);
//..processing..
}
這樣後我們在需要的地方(比如中斷)調用下面的代碼,就會向fasync_queue隊列里的設備發送SIGIO信號
,應用程序收到信號,執行處理程序
if (fasync_queue)
kill_fasync(&fasync_queue, SIGIO, POLL_IN);
好了,這下大家知道該怎麼用非同步通知機制了吧?
以下是幾點說明[1]:
1 兩個函數的原型
int fasync_helper(struct inode *inode, struct file *filp, int mode, struct fasync_struct **fa);
一個"幫忙者", 來實現 fasync 設備方法. mode 參數是傳遞給方法的相同的值, 而 fa 指針指向一個設
備特定的 fasync_struct *
void kill_fasync(struct fasync_struct *fa, int sig, int band);
如果這個驅動支持非同步通知, 這個函數可用來發送一個信號到登記在 fa 中的進程.
2.
fasync_helper 用來向等待非同步信號的設備鏈表中添加或者刪除設備文件, kill_fasync被用來通知擁有相關設備的進程. 它的參數是被傳遞的信號(常常是 SIGIO)和 band, 這幾乎都是 POLL_IN[25](但是這可用來發送"緊急"或者帶外數據, 在網路代碼里).
⑹ linux驅動模塊中添加非同步通知機制需要完成哪些工作
一 驅動方面:
1. 在設備抽象的數據結構中增加一個struct fasync_struct的指針
2. 實現設備操作中的fasync函數,這個函數很簡單,其主體就是調用內核的fasync_helper函數。
3. 在需要向用戶空間通知的地方(例如中斷中)調用內核的kill_fasync函數。
4. 在驅動的release方法中調用前面定義的fasync函數
呵呵,簡單吧,就三點。其中fasync_helper和kill_fasync都是內核函數,我們只需要調用就可以了。在1中定義的指針是一個重要參數,fasync_helper和kill_fasync會使用這個參數。
二 應用層方面
1. 利用signal或者sigaction設置SIGIO信號的處理函數
2. fcntl的F_SETOWN指令設置當前進程為設備文件owner
3. fcntl的F_SETFL指令設置FASYNC標志
完成了以上的工作的話,當內核執行到kill_fasync函數,用戶空間SIGIO函數的處理函數就會被調用了。
呵呵,看起來不是很復雜把,讓我們結合具體代碼看看就更明白了。
先從應用層代碼開始吧:
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#define MAX_LEN 100
//處理函數,沒什麼好講的,用戶自己定義
void input_handler(int num)
{
char data[MAX_LEN];
int len;
//讀取並輸出STDIN_FILENO上的輸入
len = read(STDIN_FILENO, &data, MAX_LEN);
data[len] = 0;
printf("input available:%s\n", data);
}
void main()
{
int oflags;
//啟動信號驅動機制,將SIGIO信號同input_handler函數關聯起來,一旦產生SIGIO信號,就會執行input_handler
signal(SIGIO, input_handler);
//STDIN_FILENO是打開的設備文件描述符,F_SETOWN用來決定操作是干什麼的,getpid()是個系統調用,
//功能是返回當前進程的進程號,整個函數的功能是STDIN_FILENO設置這個設備文件的擁有者為當前進程。
fcntl(STDIN_FILENO, F_SETOWN, getpid());
//得到打開文件描述符的狀態
oflags = fcntl(STDIN_FILENO, F_GETFL);
//設置文件描述符的狀態為oflags | FASYNC屬性,一旦文件描述符被設置成具有FASYNC屬性的狀態,
//也就是將設備文件切換到非同步操作模式。這時系統就會自動調用驅動程序的fasync方法。
fcntl(STDIN_FILENO, F_SETFL, oflags | FASYNC);
//最後進入一個死循環,程序什麼都不幹了,只有信號能激發input_handler的運行
//如果程序中沒有這個死循環,會立即執行完畢
while (1);
}
再看驅動層代碼,驅動層其他部分代碼不變,就是增加了一個fasync方法的實現以及一些改動
//首先是定義一個結構體,其實這個結構體存放的是一個列表,這個
//列表保存的是一系列設備文件,SIGIO信號就發送到這些設備上
static struct fasync_struct *fasync_queue;
//fasync方法的實現
static int my_fasync(int fd, struct file * filp, int on)
{
int retval;
//將該設備登記到fasync_queue隊列中去
retval=fasync_helper(fd,filp,on,&fasync_queue);
if(retval<0)
{
return retval;
}
return 0;
}
在驅動的release方法中我們再調用my_fasync方法
int my_release(struct inode *inode, struct file *filp)
{
//..processing..
drm_fasync(-1, filp, 0);
//..processing..
}這樣後我們在需要的地方(比如中斷)調用下面的代碼,就會向fasync_queue隊列里的設備發送SIGIO信號
,應用程序收到信號,執行處理程序
if (fasync_queue)
kill_fasync(&fasync_queue, SIGIO, POLL_IN);
⑺ QT編程中,怎樣實現linux中的非同步通知功能
你大可使用宏Q_SIGNALS
BTW,既然是重名
,轉換個思路