linux epoll学习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <sys/time.h>   /* For portability */
#include <sys/select.h>
 
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
Returns number of ready file descriptors, 0 on timeout, or –1 on error
 
#include <sys/select.h>
void FD_ZERO(fd_set *fdset);
void FD_SET(int fd, fd_set *fdset);
void FD_CLR(int fd, fd_set *fdset);
int FD_ISSET(int fd, fd_set *fdset);
    Returns true (1) if fd is in fdset, or false (0) otherwise
 
FD_ZERO() initializes the set pointed to by fdset to be empty.
FD_SET() adds the file descriptor fd to the set pointed to by fdset.
FD_CLR() removes the file descriptor fd from the set pointed to by fdset.
FD_ISSET() returns true if the file descriptor fd is a member of the set pointed to
by fdset.
 
struct timeval {
    time_t tv_sec;      /* Seconds */
    suseconds_t tv_usec;/* Microseconds (long int) */
};
 
typedef struct
{
    /*XPG4.2requiresthismembername.Otherwiseavoidthename
    fromtheglobalnamespace.*/
    #ifdef__USE_XOPEN
    __fd_maskfds_bits[__FD_SETSIZE/__NFDBITS];
    #define__FDS_BITS(set)((set)->fds_bits)
    #else
    __fd_mask__fds_bits[__FD_SETSIZE/__NFDBITS];
    #define__FDS_BITS(set)((set)->__fds_bits)
    #endif
}fd_set; /* linux下为 1024/8 = 128 Bytes */
 
------------------
 
 
#include <sys/epoll.h>
int epoll_create(int size);
    Returns file descriptor on success, or –1 on error
 
Starting with kernel 2.6.27, Linux supports a new system call, epoll_create1().
This system call performs the same task as epoll_create(), but drops the obsolete
size argument and adds a flags argument that can be used to modify the behavior
of the system call. One flag is currently supported: EPOLL_CLOEXEC, which causes
the kernel to enable the close-on-exec flag (FD_CLOEXEC) for the new file descriptor.
This flag is useful for the same reasons as the open() O_CLOEXEC flag described in
Section 4.3.1
 
#include <sys/epoll.h>
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *ev);
    Returns 0 on success, or –1 on error
 
The fd argument identifies which of the file descriptors in the interest list is to have
its settings modified. This argument can be a file descriptor for a 'pipe, FIFO,
socket, POSIX message queue, inotify instance, terminal, device, or even another epoll
descriptor' (i.e., we can build a kind of hierarchy of monitored descriptors). However,
fd can’t be a file descriptor for a regular file or a directory (the error EPERM results).
 
 
The op argument specifies the operation to be performed, and has one of the
following values:
EPOLL_CTL_ADD
EPOLL_CTL_MOD
EPOLL_CTL_DEL
 
共12字节:
struct epoll_event {
    uint32_t events;        /* epoll events (bit mask) */
    epoll_data_t data;      /* User data */
};
 
The data field of the epoll_event structure is typed as follows:
typedef union epoll_data {
    void *ptr;      //Pointer to user-defined data
    int fd;         //File descriptor */
    uint32_t u32;   //32-bit integer */
    uint64_t u64;   //64-bit integer */
} epoll_data_t;
 
#include <sys/epoll.h>
int epoll_wait(int epfd, struct epoll_event *evlist, int maxevents, int timeout);
    Returns number of ready file descriptors, 0 on timeout, or –1 on error
 
 
Table 63-8: Bit-mask values for the epoll events field Bit
EPOLLIN             Data other than high-priority data can be read
EPOLLPRI            High-priority data can be read
EPOLLRDHUP          Shutdown on peer socket (since Linux 2.6.17)
EPOLLOUT            Normal data can be written
EPOLLET             Employ edge-triggered event notification
EPOLLONESHOT        Disable monitoring after event notification
EPOLLERR            An error has occurred
EPOLLHUP            A hangup has occurred
 
Input to            Returned by
epoll_ctl()?        epoll_wait()?
• •
• •
• •
• •
 
 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// gcc epoll_input_fifo.c lib/error_functions.c lib/get_num.c -Ilib  -o epoll_input_fifo.out
#include <sys/epoll.h>
#include <fcntl.h>
#include "tlpi_hdr.h"
 
#define MAX_BUF 1000
#define MAX_EVENTS 5
 
int main(int argc, char *argv[]){
    int epfd, ready, fd, s, j, numOpenFds;
    struct epoll_event ev;
    struct epoll_event evlist[MAX_EVENTS];
    char buf[MAX_BUF];
 
    printf("EPOLLIN: 0x%x\n", EPOLLIN);
    printf("EPOLLHUP: 0x%x\n", EPOLLHUP);
    printf("EPOLLERR: 0x%x\n", EPOLLERR);
 
    if (argc < 2 || strcmp(argv[1], "--help") == 0)
        usageErr("%s file...\n", argv[0]);
 
    epfd = epoll_create(argc-1);
    if(epfd == -1)
        errExit("epoll_create");
 
    for(j = 1; j < argc; j++){
        fd = open(argv[j], O_RDONLY);
        if(fd == -1){
            errExit("open");
        }
        printf("Opened '%s' on fd %d\n", argv[j], fd);
 
        ev.events = EPOLLIN;  // Only interested in input events
        ev.data.fd = fd;
        if(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1)
            errExit("epoll_ctl");
    }
    numOpenFds = argc - 1;
    while(numOpenFds > 0){
        printf("About to epoll_wait()\n");
        ready = epoll_wait(epfd, evlist, MAX_EVENTS, -1);
        if(ready == -1){
            if(errno == EINTR)
                continue;
            else
                errExit("epoll_wait");
        }
        printf("Ready: %d\n", ready);
        for(j=0;j<ready;j++){
            printf("  fd=%d; events: %s%s%s\n", evlist[j].data.fd,
                    (evlist[j].events & EPOLLIN) ? "EPOLLIN " : "",
                    (evlist[j].events & EPOLLHUP) ? "EPOLLHUP " : "",
                    (evlist[j].events & EPOLLERR) ? "EPOLLERR " : "");
            if(evlist[j].events & EPOLLIN){
                s = read(evlist[j].data.fd, buf, MAX_BUF);
                if(s == -1)
                    errExit("read");
                printf("    read %d bytes: %.*s\n", s,s,buf);
            } else if(evlist[j].events & (EPOLLHUP | EPOLLERR)) {
                printf("    closing fd %d\n", evlist[j].data.fd);
                if(close(evlist[j].data.fd)==-1)
                    errExit("close");
                numOpenFds--;
            }
        }
    }
    printf("All file descriptors closed. bye\n");
    exit(EXIT_SUCCESS);
}

 

 

from: 《The Linux Programming Interface》P1355

posted @   庚武  Views(552)  Comments(0Edit  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
历史上的今天:
2013-04-06 CentOS访问Windows磁盘分区
2012-04-06 DECLARE_HANDLE 宏,#,## 预处理指令
2012-04-06 DLL建立读写共享节区(Segment)
点击右上角即可分享
微信分享提示