epoll介紹及使用

小程序功能:簡單的父子進程之間的通信,子進程負責每隔1s不斷髮送"message"給父進程,不須要跑多個應用實例,不須要用戶輸入。linux

首先上代碼

#include<assert.h>
#include<signal.h>
#include<stdio.h>
#include<sys/epoll.h>
#include<sys/time.h>
#include<sys/wait.h>
#include<unistd.h>

int  fd[2];
int* write_fd;
int* read_fd;
const char msg[] = {'m','e','s','s','a','g','e'};

void SigHandler(int){
    size_t bytes = write(*write_fd, msg, sizeof(msg));
    printf("children process msg have writed : %ld bytes\n", bytes);
}

void ChildrenProcess() {
    struct sigaction sa;
    sa.sa_flags     =   0;
    sa.sa_handler   =   SigHandler;
    sigaction(SIGALRM, &sa, NULL);

    struct itimerval tick   =   {0};
    tick.it_value.tv_sec    =   1;   // 1s後將啓動定時器
    tick.it_interval.tv_sec =   1;   // 定時器啓動後,每隔1s將執行相應的函數

    // setitimer將觸發SIGALRM信號,此處使用的是ITIMER_REAL,因此對應的是SIGALRM信號
    assert(setitimer(ITIMER_REAL, &tick, NULL) == 0);
    while(true) {
        pause();
    }
}

void FatherProcess() {
    epoll_event ev;
    epoll_event events[1];
    char buf[1024]  =   {0};
    int epoll_fd    =   epoll_create(1);
    ev.data.fd      =   *read_fd;
    ev.events       =   EPOLLIN | EPOLLET;
    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, *read_fd, &ev);

    while (true) {
        int fds = epoll_wait(epoll_fd, events, sizeof(events), -1);
        if(events[0].data.fd == *read_fd) {
            size_t bytes = read(*read_fd, buf, sizeof(buf));
            printf("father process read %ld bytes = %s\n", bytes, buf);
        }
    }

    int status;
    wait(&status);
}

int main() {
    int ret = pipe(fd);
    if (ret != 0) {
        printf("pipe failed\n");
        return -1;
    }
    write_fd = &fd[1];
    read_fd  = &fd[0];

    pid_t pid = fork();
    if (pid == 0) {//child process
        ChildrenProcess();
    } else if (pid > 0) {//father process
        FatherProcess();
    }

    return 0;
}

 

函數功能分析

一、int setitimer(int which, const struct itimerval value, struct itimerval ovalue);小程序

which:間歇計時器類型,有三種選擇:
ITIMER_REAL //數值爲0,計時器的值實時遞減,發送的信號是SIGALRM。
ITIMER_VIRTUAL //數值爲1,進程執行時遞減計時器的值,發送的信號是SIGVTALRM。
ITIMER_PROF //數值爲2,進程和系統執行時都遞減計時器的值,發送的信號是SIGPROF。數組

功能:在linux下若是定時若是要求不太精確的話,使用alarm()和signal()就好了(精確到秒),可是若是想要實現精度較高的定時功能的話,就要使用setitimer函數。setitimer()爲Linux的API,並不是C語言的Standard Library,setitimer()有兩個功能,一是指定一段時間後,才執行某個function,二是每間格一段時間就執行某個function。it_interval指定間隔時間,it_value指定初始定時時間。若是隻指定it_value,就是實現一次定時;若是同時指定 it_interval,則超時後,系統會從新初始化it_value爲it_interval,實現重複定時;二者都清零,則會清除定時器。 固然,若是是以setitimer提供的定時器來休眠,只需阻塞等待定時器信號就能夠了。函數

 

二、int sigaction(int signum, const struct sigaction act, struct sigaction oldact);
signum:要操做的信號。
act:要設置的對信號的新處理方式。
oldact:原來對信號的處理方式。spa

 

三、int pipe(int filedes[2]);
返回值:成功,返回0,不然返回-1。參數數組包含pipe使用的兩個文件的描述符。fd[0]:讀管道,fd[1]:寫管道。必須在fork()中調用pipe(),不然子進程不會繼承文件描述符。兩個進程不共享祖先進程,就不能使用pipe。可是可使用命名管道。 管道是一種把兩個進程之間的標準輸入和標準輸出鏈接起來的機制,從而提供一種讓多個進程間通訊的方法,當進程建立管道時,每次 都須要提供兩個文件描述符來操做管道。其中一個對管道進行寫操做,另外一個對管道進行讀操做。對管道的讀寫與通常的IO系統函數一致,使用write()函數寫入數據,使用read()讀出數據。code

相關文章
相關標籤/搜索