搜索引擎優(yōu)化的基本方法成都網(wǎng)站優(yōu)化公司
Linux版本號4.1.15? ?芯片I.MX6ULL? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 大叔學(xué)Linux? ? 品人間百味? 思文短情長?
? ? ? ? 在正式開始今天的筆記之前談一下工作中遇見的一個問題。
? ? ? ? 本篇筆記主要學(xué)習(xí)Linux 阻塞和非阻塞 IO 實驗,主要包括阻塞和非阻塞簡介、等待隊列、輪詢、poll操作、阻塞和非阻塞實驗。其中重點內(nèi)容為阻塞和非阻塞實驗。
? ? ? ? 本筆記的思維導(dǎo)圖如下:
一、阻塞和非阻塞IO
1.阻塞和非阻塞簡介
? ? ? ? 1)阻塞
1 int fd;
2 int data = 0;
3 4
fd = open("/dev/xxx_dev", O_RDWR); /* 阻塞方式打開 */
5 ret = read(fd, &data, sizeof(data)); /* 讀取數(shù)據(jù) */
2)非阻塞
1 int fd;
2 int data = 0;
3 4
fd = open("/dev/xxx_dev", O_RDWR); /* 阻塞方式打開 */
5 ret = read(fd, &data, sizeof(data)); /* 讀取數(shù)據(jù) */
????????參數(shù)“O_NONBLOCK”,表示以非阻塞方式打開設(shè)備,這樣從設(shè)備中讀取數(shù)據(jù)的時候就是非阻塞方式的了。
2.等待隊列
? ? ? ? 1)等待隊列頭
????????等待隊列頭使用結(jié)構(gòu)體wait_queue_head_t 表示:
39 struct __wait_queue_head {
40 spinlock_t lock;
41 struct list_head task_list;
42 };
43 typedef struct __wait_queue_head wait_queue_head_t;
????????init_waitqueue_head 函數(shù)初始化等待隊列頭
void init_waitqueue_head(wait_queue_head_t *q)//參數(shù) q 就是要初始化的等待隊列頭。
也可以使用宏 DECLARE_WAIT_QUEUE_HEAD 來一次性完成等待隊列頭的定義的初始化。
? ? ? ? 2)等待隊列項
結(jié)構(gòu)體 wait_queue_t 表示等待隊列項,結(jié)構(gòu)體內(nèi)容如下:
struct __wait_queue {
unsigned int flags;
void *private;
wait_queue_func_t func;
struct list_head task_list;
};
typedef struct __wait_queue wait_queue_t;
????????宏DECLARE_WAITQUEUE 就是給當(dāng)前正在運行的進程創(chuàng)建并初始化了一個等待隊列項。
DECLARE_WAITQUEUE(name, tsk)
????????name 就是等待隊列項的名字, tsk 表示這個等待隊列項屬于哪個任務(wù)(進程),一般設(shè)置為
current , 在 Linux 內(nèi) 核 中 current 相 當(dāng) 于 一 個 全 局 變 量 , 表 示 當(dāng) 前 進 程 。
? ? ? ? 3)將隊列項添加/刪除隊列頭
????????只有添加到等待隊列頭中以后進程才能進入休眠態(tài)。等待隊列項添加 API 函數(shù)如下:
void add_wait_queue(wait_queue_head_t *q,
wait_queue_t *wait)
????????等待隊列項移除 API 函數(shù)如下:
void remove_wait_queue(wait_queue_head_t *q,
wait_queue_t *wait)
? ? ? ? 4)等待喚醒
void wake_up(wait_queue_head_t *q)
void wake_up_interruptible(wait_queue_head_t *q)
? ? ? ?wake_up_interruptible 函數(shù)只能喚醒處于 TASK_INTERRUPTIBLE 狀態(tài)的進程。
5)等待事件
函數(shù) | 描述 | |||
? |
? | |||
|
? | |||
|
? | |||
? |
? |
3.輪詢【非阻塞】
? ? ? ? 1)select函數(shù)????????
int select(int nfds,
fd_set *readfds,
fd_set *writefds,
fd_set *exceptfds,
struct timeval *timeout)
? ? ? ? fd_set 類型變量的每一個位都代表了一個文件描述符。
void FD_ZERO(fd_set *set)
void FD_SET(int fd, fd_set *set)
void FD_CLR(int fd, fd_set *set)
int FD_ISSET(int fd, fd_set *set)
? ? ? ? 2)poll函數(shù)
? ? ? ? 沒有最大文件描述符限制。
int poll(struct pollfd *fds,
nfds_t nfds,
int timeout)
? ? ? ? 3)epoll函數(shù)
????????epoll 就是為處理大并發(fā)而準備的。
int epoll_create(int size)
返回值: epoll 句柄,如果為-1 的話表示創(chuàng)建失敗。
????????epoll_ctl 函數(shù)向其中添加要監(jiān)視的文件描述符以及監(jiān)視的事件, epoll_ctl 函數(shù)原型如下所示:
int epoll_ctl(int epfd,
int op,
int fd,
struct epoll_event *event)
epoll_wait 函數(shù)來等待事件的發(fā)生:
int epoll_wait(int epfd,
struct epoll_event *events,
int maxevents,
int timeout)
4.poll操作
poll 函數(shù)原型如下所示:
unsigned int (*poll) (struct file *filp, struct poll_table_struct *wait)
poll_wait 函數(shù)不會引起阻塞,只是將應(yīng)用程序添加到 poll_table 中, poll_wait 函數(shù)原型如下:
void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
????????參數(shù) wait_address 是要添加到 poll_table 中的等待隊列頭,參數(shù) p 就是 poll_table,就是
file_operations 中 poll 函數(shù)的 wait 參數(shù)。
二、總結(jié)
????????本篇筆記主要學(xué)習(xí)Linux 阻塞和非阻塞 IO 實驗,主要包括阻塞和非阻塞簡介、等待隊列、輪詢、poll操作。
以下內(nèi)容將在下一篇筆記中進行學(xué)習(xí):
二、阻塞IO實驗
1.硬件原理圖分析
2.實驗程序
3.運行測試
三、非阻塞IO實驗
1.硬件原理圖分析
2.實驗程序
3.運行測試
本文為參考正點原子開發(fā)板配套教程整理而得,僅用于學(xué)習(xí)交流使用,不得用于商業(yè)用途。