1. ioctl一些參數
#include <sys/ioctl.h>
ioctl(int fd, int request, ...)
fcntl(int fd, int request, ...)
// fd 爲需要對哪個文件描述符進行操作
// 對fd進行操作的request
//... 爲參數
在nginx 的創建worker 進程時有以下應用場景
1.將描述符設爲非阻塞
ioctl(s, FIONBIO, &nb);
2.設置文件描述符異步驅動
ioctl(s, FIOASYNC, &on)
3.設置文件描述符所屬於的pid
fcntl(s, F_SETOWN, ngx_pid)
4.子進程任可使用該fd,而用exec 執行的程序關閉fd
fcntl(ngx_processes[s].channel[0], F_SETFD, FD_CLOEXEC)
2.socketpair
socketpair(AF_UNIX, SOCK_STREAM, 0, int s[2])
//這個函數,創建出兩個fd,從而可以全雙工的進行通信
可用於父子進程的通信,子進程共享s[2],
父進程關閉一個fd,子進程關閉另一個fd
3. ngx_processes 數據結構
pid保存了該process 的pid
channer 保存了該process的fd,其中[0] 爲父進程fd 而[1]爲子進程fd,
typedef struct {
ngx_pid_t pid;
int status;
ngx_socket_t channel[2];
ngx_spawn_proc_pt proc;
void *data;
char *name;
...
4. 開啓流程
1. 從ngx_processes 數組中遍歷,如果其中pid爲-1,就表示用這個slot作爲這個process的存儲結構
2. socketpair 生成一對fd對
3. ioctrl fnctrl設置fd屬性
4. ngx_process_slot存儲當前的slot
5. fork 子進程
6. 子進程進入cycle,等待事件,並 close channel[0] 這邊有一點需要注意,因爲fork之後,所有的ngx_processes 在子進程也被複制了一份,所以在ngx_last_process 前面的且不等於當前ngx_process_slot的channel[1] fd需要關閉
7. 然後給此fd添加epoll事件
8. 父進程更新ngx_last_process,如果s== ngx_last_process ngx last_process++
其中ngx_event_t 中的data保存的是 connection
handler保存的是處理函數