Skip to content

Commit dbc939b

Browse files
authored
Merge pull request #1558 from libumem/dev
epoll support
2 parents fe462b8 + 3675f55 commit dbc939b

File tree

9 files changed

+664
-6
lines changed

9 files changed

+664
-6
lines changed

examples/src/linux/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ TARGETS = \
3333
x8664_hello_cpp \
3434
x8664_hello_cpp_static \
3535
x8664_cloexec_test \
36+
x8664_linux_onestraw \
3637
patch_test.bin
3738

3839
.PHONY: all clean
@@ -124,7 +125,10 @@ libpatch_test.so: patch_test.so.h patch_test.so.c
124125
$(CC) $(CPPFLAGS) -Wall -s -O0 -shared -fpic -o $@ patch_test.so.c
125126

126127
patch_test.bin: patch_test.bin.c libpatch_test.so
128+
127129
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $^
130+
x8664_onestraw_server: x8664_linux_onestraw.c
131+
$(CC) $(CPPFLAGS) $(CFLAGS) -m64 -o $@ $<
128132

129133
$(OBJS):%.o:%.c
130134
$(CC) $(CFLAGS) -c $< -o $@
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#define MAX_EVENTS 5
2+
#define READ_SIZE 10
3+
#include <stdio.h> // for fprintf()
4+
#include <unistd.h> // for close(), read()
5+
#include <sys/epoll.h> // for epoll_create1(), epoll_ctl(), struct epoll_event
6+
#include <string.h> // for strncmp
7+
8+
int main()
9+
{
10+
//setvbuf(stdin, NULL, _IONBF, 0);
11+
int running = 1, event_count, i;
12+
size_t bytes_read;
13+
char read_buffer[READ_SIZE + 1];
14+
struct epoll_event event, events[MAX_EVENTS];
15+
int epoll_fd = epoll_create1(0);
16+
17+
if (epoll_fd == -1) {
18+
fprintf(stderr, "Failed to create epoll file descriptor\n");
19+
return 1;
20+
}
21+
22+
event.events = EPOLLIN;
23+
event.data.fd = 0;
24+
25+
if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, 0, &event))
26+
{
27+
fprintf(stderr, "Failed to add file descriptor to epoll\n");
28+
close(epoll_fd);
29+
return 1;
30+
}
31+
32+
while (running) {
33+
printf("\nPolling for input...\n");
34+
event_count = epoll_wait(epoll_fd, events, MAX_EVENTS, 30000);
35+
printf("%d ready events\n", event_count);
36+
for (i = 0; i < event_count; i++) {
37+
printf("Reading file descriptor '%d' -- ", events[i].data.fd);
38+
bytes_read = read(events[i].data.fd, read_buffer, READ_SIZE);
39+
printf("%zd bytes read.\n", bytes_read);
40+
read_buffer[bytes_read] = '\0';
41+
printf("Read '%s'\n", read_buffer);
42+
43+
if(!strncmp(read_buffer, "stop\n", 5))
44+
running = 0;
45+
}
46+
}
47+
48+
if (close(epoll_fd)) {
49+
fprintf(stderr, "Failed to close epoll file descriptor\n");
50+
return 1;
51+
}
52+
53+
return 0;
54+
}
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
/*
2+
* Attention:
3+
* To keep things simple, do not handle socket/bind/listen/.../epoll_create/epoll_wait API error
4+
*/
5+
#include <arpa/inet.h>
6+
#include <sys/types.h>
7+
#include <sys/socket.h>
8+
#include <netdb.h>
9+
#include <string.h>
10+
#include <unistd.h>
11+
#include <fcntl.h>
12+
#include <sys/epoll.h>
13+
#include <errno.h>
14+
#include <stdio.h>
15+
#include <stdlib.h>
16+
17+
#define DEFAULT_PORT 8000
18+
#define MAX_CONN 16
19+
#define MAX_EVENTS 32
20+
#define BUF_SIZE 16
21+
#define MAX_LINE 256
22+
23+
void server_run();
24+
void client_run();
25+
26+
int main(int argc, char *argv[])
27+
{
28+
int opt;
29+
char role = 's';
30+
while ((opt = getopt(argc, argv, "cs")) != -1) {
31+
switch (opt) {
32+
case 'c':
33+
role = 'c';
34+
break;
35+
case 's':
36+
break;
37+
default:
38+
printf("usage: %s [-cs]\n", argv[0]);
39+
exit(1);
40+
}
41+
}
42+
if (role == 's') {
43+
server_run();
44+
} else {
45+
client_run();
46+
}
47+
return 0;
48+
}
49+
50+
/*
51+
* register events of fd to epfd
52+
*/
53+
static void epoll_ctl_add(int epfd, int fd, uint32_t events)
54+
{
55+
struct epoll_event ev;
56+
ev.events = events;
57+
ev.data.fd = fd;
58+
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
59+
perror("epoll_ctl()\n");
60+
exit(1);
61+
}
62+
}
63+
64+
static void set_sockaddr(struct sockaddr_in *addr)
65+
{
66+
bzero((char *)addr, sizeof(struct sockaddr_in));
67+
addr->sin_family = AF_INET;
68+
addr->sin_addr.s_addr = INADDR_ANY;
69+
addr->sin_port = htons(DEFAULT_PORT);
70+
}
71+
72+
static int setnonblocking(int sockfd)
73+
{
74+
if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK) ==
75+
-1) {
76+
return -1;
77+
}
78+
return 0;
79+
}
80+
81+
/*
82+
* epoll echo server
83+
*/
84+
void server_run()
85+
{
86+
int i;
87+
int n;
88+
int epfd;
89+
int nfds;
90+
int listen_sock;
91+
int conn_sock;
92+
int socklen;
93+
char buf[BUF_SIZE];
94+
struct sockaddr_in srv_addr;
95+
struct sockaddr_in cli_addr;
96+
struct epoll_event events[MAX_EVENTS];
97+
98+
listen_sock = socket(AF_INET, SOCK_STREAM, 0);
99+
100+
set_sockaddr(&srv_addr);
101+
bind(listen_sock, (struct sockaddr *)&srv_addr, sizeof(srv_addr));
102+
103+
setnonblocking(listen_sock);
104+
listen(listen_sock, MAX_CONN);
105+
106+
epfd = epoll_create(1);
107+
epoll_ctl_add(epfd, listen_sock, EPOLLIN | EPOLLOUT | EPOLLET);
108+
109+
socklen = sizeof(cli_addr);
110+
int a;
111+
for (a = 0; a < 2; a++) {
112+
nfds = epoll_wait(epfd, events, MAX_EVENTS, -1);
113+
for (i = 0; i < nfds; i++) {
114+
if (events[i].data.fd == listen_sock) {
115+
/* handle new connection */
116+
conn_sock =
117+
accept(listen_sock,
118+
(struct sockaddr *)&cli_addr,
119+
&socklen);
120+
121+
inet_ntop(AF_INET, (char *)&(cli_addr.sin_addr),
122+
buf, sizeof(cli_addr));
123+
printf("[+] connected with %s:%d\n", buf,
124+
ntohs(cli_addr.sin_port));
125+
126+
setnonblocking(conn_sock);
127+
epoll_ctl_add(epfd, conn_sock,
128+
EPOLLIN | EPOLLET | EPOLLRDHUP |
129+
EPOLLHUP);
130+
} else if (events[i].events & EPOLLIN) {
131+
/* handle EPOLLIN event */
132+
for (;;) {
133+
bzero(buf, sizeof(buf));
134+
n = read(events[i].data.fd, buf,
135+
sizeof(buf));
136+
if (n <= 0 /* || errno == EAGAIN */ ) {
137+
break;
138+
} else {
139+
printf("[+] data: %s\n", buf);
140+
write(events[i].data.fd, buf,
141+
strlen(buf));
142+
}
143+
}
144+
} else {
145+
printf("[+] unexpected\n");
146+
}
147+
/* check if the connection is closing */
148+
if (events[i].events & (EPOLLRDHUP | EPOLLHUP)) {
149+
printf("[+] connection closed\n");
150+
epoll_ctl(epfd, EPOLL_CTL_DEL,
151+
events[i].data.fd, NULL);
152+
close(events[i].data.fd);
153+
continue;
154+
}
155+
}
156+
}
157+
}
158+
159+
/*
160+
* test clinet
161+
*/
162+
void client_run()
163+
{
164+
int n;
165+
int c;
166+
int sockfd;
167+
char buf[MAX_LINE];
168+
struct sockaddr_in srv_addr;
169+
170+
sockfd = socket(AF_INET, SOCK_STREAM, 0);
171+
172+
set_sockaddr(&srv_addr);
173+
174+
if (connect(sockfd, (struct sockaddr *)&srv_addr, sizeof(srv_addr)) < 0) {
175+
perror("connect()");
176+
exit(1);
177+
}
178+
179+
for (;;) {
180+
printf("input: ");
181+
fgets(buf, sizeof(buf), stdin);
182+
c = strlen(buf) - 1;
183+
buf[c] = '\0';
184+
write(sockfd, buf, c + 1);
185+
186+
bzero(buf, sizeof(buf));
187+
while (errno != EAGAIN
188+
&& (n = read(sockfd, buf, sizeof(buf))) > 0) {
189+
printf("echo: %s\n", buf);
190+
bzero(buf, sizeof(buf));
191+
192+
c -= n;
193+
if (c <= 0) {
194+
break;
195+
}
196+
}
197+
}
198+
close(sockfd);
199+
}

qiling/os/posix/const.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,3 +1064,29 @@ class qnx_mmap_prot_flags(QlPrettyFlag):
10641064
SHMDT = 22
10651065
SHMGET = 23
10661066
SHMCTL = 24
1067+
1068+
# see: https://elixir.bootlin.com/linux/v5.19.17/source/include/uapi/linux/eventpoll.h
1069+
EPOLL_CTL_ADD = 1
1070+
EPOLL_CTL_DEL = 2
1071+
EPOLL_CTL_MOD = 3
1072+
1073+
EPOLLIN = 0x00000001
1074+
EPOLLPRI = 0x00000002
1075+
EPOLLOUT = 0x00000004
1076+
EPOLLERR = 0x00000008
1077+
EPOLLHUP = 0x00000010
1078+
EPOLLNVAL = 0x00000020
1079+
EPOLLRDNORM = 0x00000040
1080+
EPOLLRDBAND = 0x00000080
1081+
EPOLLWRNORM = 0x00000100
1082+
EPOLLWRBAND = 0x00000200
1083+
EPOLLMSG = 0x00000400
1084+
EPOLLRDHUP = 0x00002000
1085+
1086+
# TODO: should be aligned to emulated system's close-on-exec value
1087+
EPOLL_CLOEXEC = 0o2000000
1088+
1089+
EPOLLEXCLUSIVE = 0b1 << 28
1090+
EPOLLWAKEUP = 0b1 << 29
1091+
EPOLLONESHOT = 0b1 << 30
1092+
EPOLLET = 0b1 << 31

qiling/os/posix/syscall/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,4 @@
3131
from .unistd import *
3232
from .utsname import *
3333
from .wait import *
34+
from .epoll import *

0 commit comments

Comments
 (0)