Commit ce434124ab445b5a203c8870baf062cb9899aaa8
0 parents
Initial version
Showing
26 changed files
with
1258 additions
and
0 deletions
eintrc.c
0 → 100644
1 | +++ a/eintrc.c | |
1 | +/* Make the necessary includes and set up the variables. */ | |
2 | + | |
3 | +#include <sys/types.h> | |
4 | +#include <sys/socket.h> | |
5 | +#include <stdio.h> | |
6 | +#include <stdlib.h> | |
7 | +#include <netinet/in.h> | |
8 | +#include <arpa/inet.h> | |
9 | +#include <unistd.h> | |
10 | +#include <signal.h> | |
11 | + | |
12 | +void | |
13 | +alarmhandler (int s) | |
14 | +{ | |
15 | + signal (SIGALRM, alarmhandler); | |
16 | + alarm (1); | |
17 | +} | |
18 | + | |
19 | +int | |
20 | +main () | |
21 | +{ | |
22 | + int sockfd; | |
23 | + socklen_t len; | |
24 | + struct sockaddr_in address; | |
25 | + int result; | |
26 | + ssize_t count; | |
27 | + char buffer[1024 * 1024]; | |
28 | + signal (SIGALRM, alarmhandler); | |
29 | + alarm (1); | |
30 | + | |
31 | + /* Create a socket for the client. */ | |
32 | + | |
33 | + sockfd = socket (AF_INET, SOCK_STREAM, 0); | |
34 | + | |
35 | + /* Name the socket, as agreed with the server. */ | |
36 | + | |
37 | + address.sin_family = AF_INET; | |
38 | + address.sin_addr.s_addr = inet_addr ("127.0.0.1"); | |
39 | + address.sin_port = htons (9734); | |
40 | + len = sizeof (address); | |
41 | + | |
42 | + /* Now connect our socket to the server's socket. */ | |
43 | + | |
44 | + result = connect (sockfd, (struct sockaddr *) &address, len); | |
45 | + | |
46 | + if (result == -1) | |
47 | + { | |
48 | + perror ("oops: eintrc"); | |
49 | + exit (1); | |
50 | + } | |
51 | + | |
52 | + /* We can now read/write via sockfd. */ | |
53 | + while (1) | |
54 | + { | |
55 | + | |
56 | + count = write (sockfd, buffer, 1024 * 1024); | |
57 | + if (count == -1) | |
58 | + perror ("write"); | |
59 | + else | |
60 | + printf ("Wrote %zd bytes\n", count); | |
61 | + } | |
62 | +} | ... | ... |
eintrs.c
0 → 100644
1 | +++ a/eintrs.c | |
1 | +#include <sys/types.h> | |
2 | +#include <sys/socket.h> | |
3 | +#include <stdio.h> | |
4 | +#include <netinet/in.h> | |
5 | +#include <signal.h> | |
6 | +#include <unistd.h> | |
7 | + | |
8 | +int | |
9 | +main () | |
10 | +{ | |
11 | + ssize_t count; | |
12 | + char buffer[1024 * 1024]; | |
13 | + int server_sockfd, client_sockfd; | |
14 | + socklen_t server_len, client_len; | |
15 | + struct sockaddr_in server_address; | |
16 | + struct sockaddr_in client_address; | |
17 | + | |
18 | + server_sockfd = socket (AF_INET, SOCK_STREAM, 0); | |
19 | + | |
20 | + server_address.sin_family = AF_INET; | |
21 | + server_address.sin_addr.s_addr = htonl (INADDR_ANY); | |
22 | + server_address.sin_port = htons (9734); | |
23 | + server_len = sizeof (server_address); | |
24 | + bind (server_sockfd, (struct sockaddr *) &server_address, server_len); | |
25 | + | |
26 | + /* Create a connection queue and wait for clients. */ | |
27 | + | |
28 | + listen (server_sockfd, 5); | |
29 | + | |
30 | + printf ("server waiting\n"); | |
31 | + | |
32 | + /* Accept connection. */ | |
33 | + | |
34 | + client_len = sizeof (client_address); | |
35 | + client_sockfd = accept (server_sockfd, | |
36 | + (struct sockaddr *) &client_address, &client_len); | |
37 | + | |
38 | + while (1) | |
39 | + { | |
40 | + count = read (client_sockfd, buffer, 1024 * 1024); | |
41 | + printf ("Read %zd bytes\n", count); | |
42 | + } | |
43 | +} | ... | ... |
epoll1.c
0 → 100644
1 | +++ a/epoll1.c | |
1 | +#include <stdio.h> // for fprintf() | |
2 | +#include <unistd.h> // for close() | |
3 | +#include <sys/epoll.h> // for epoll_create1() | |
4 | + | |
5 | +int main() | |
6 | +{ | |
7 | + int epoll_fd = epoll_create1(0); | |
8 | + | |
9 | + if(epoll_fd == -1) | |
10 | + { | |
11 | + fprintf(stderr, "Failed to create epoll file descriptor\n"); | |
12 | + return 1; | |
13 | + } | |
14 | + | |
15 | + if(close(epoll_fd)) | |
16 | + { | |
17 | + fprintf(stderr, "Failed to close epoll file descriptor\n"); | |
18 | + return 1; | |
19 | + } | |
20 | + return 0; | |
21 | +} | |
22 | + | ... | ... |
epoll2.c
0 → 100644
1 | +++ a/epoll2.c | |
1 | +#include <stdio.h> // for fprintf() | |
2 | +#include <unistd.h> // for close() | |
3 | +#include <sys/epoll.h> // for epoll_create1(), epoll_ctl(), struct epoll_event | |
4 | + | |
5 | +int main() | |
6 | +{ | |
7 | + struct epoll_event event; | |
8 | + int epoll_fd = epoll_create1(0); | |
9 | + | |
10 | + if(epoll_fd == -1) | |
11 | + { | |
12 | + fprintf(stderr, "Failed to create epoll file descriptor\n"); | |
13 | + return 1; | |
14 | + } | |
15 | + | |
16 | + event.events = EPOLLIN; | |
17 | + event.data.fd = 0; | |
18 | + | |
19 | + if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, 0, &event)) | |
20 | + { | |
21 | + fprintf(stderr, "Failed to add file descriptor to epoll\n"); | |
22 | + close(epoll_fd); | |
23 | + return 1; | |
24 | + } | |
25 | + | |
26 | + if(close(epoll_fd)) | |
27 | + { | |
28 | + fprintf(stderr, "Failed to close epoll file descriptor\n"); | |
29 | + return 1; | |
30 | + } | |
31 | + return 0; | |
32 | +} | |
33 | + | ... | ... |
epoll3.c
0 → 100644
1 | +++ a/epoll3.c | |
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 | + int running = 1, event_count, i; | |
11 | + size_t bytes_read; | |
12 | + char read_buffer[READ_SIZE + 1]; | |
13 | + struct epoll_event event, events[MAX_EVENTS]; | |
14 | + int epoll_fd = epoll_create1(0); | |
15 | + | |
16 | + if(epoll_fd == -1) | |
17 | + { | |
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 | + { | |
34 | + printf("\nPolling for input...\n"); | |
35 | + event_count = epoll_wait(epoll_fd, events, MAX_EVENTS, 30000); | |
36 | + printf("%d ready events\n", event_count); | |
37 | + for(i = 0; i < event_count; i++) | |
38 | + { | |
39 | + printf("Reading file descriptor '%d' -- ", events[i].data.fd); | |
40 | + bytes_read = read(events[i].data.fd, read_buffer, READ_SIZE); | |
41 | + printf("%zd bytes read.\n", bytes_read); | |
42 | + read_buffer[bytes_read] = '\0'; | |
43 | + printf("Read '%s'\n", read_buffer); | |
44 | + | |
45 | + if(!strncmp(read_buffer, "stop\n", 5)) | |
46 | + running = 0; | |
47 | + } | |
48 | + } | |
49 | + | |
50 | + if(close(epoll_fd)) | |
51 | + { | |
52 | + fprintf(stderr, "Failed to close epoll file descriptor\n"); | |
53 | + return 1; | |
54 | + } | |
55 | + return 0; | |
56 | +} | |
57 | + | ... | ... |
epoll4.c
0 → 100644
1 | +++ a/epoll4.c | |
1 | +/* | |
2 | + * Attention: | |
3 | + * To keep things simple, do not handle socket/bind/listen/.../epoll_create/epoll_wait API error | |
4 | + */ | |
5 | +#include <sys/types.h> | |
6 | +#include <sys/socket.h> | |
7 | +#include <netdb.h> | |
8 | +#include <string.h> | |
9 | +#include <unistd.h> | |
10 | +#include <fcntl.h> | |
11 | +#include <sys/epoll.h> | |
12 | +#include <errno.h> | |
13 | +#include <stdio.h> | |
14 | +#include <stdlib.h> | |
15 | +#include <arpa/inet.h> | |
16 | + | |
17 | + | |
18 | +#define DEFAULT_PORT 9734 | |
19 | +#define MAX_CONN 16 | |
20 | +#define MAX_EVENTS 32 | |
21 | +#define BUF_SIZE 16 | |
22 | +#define MAX_LINE 256 | |
23 | + | |
24 | +void server_run(); | |
25 | +void client_run(); | |
26 | + | |
27 | +int main(int argc, char *argv[]) | |
28 | +{ | |
29 | + int opt; | |
30 | + char role = 's'; | |
31 | + while ((opt = getopt(argc, argv, "cs")) != -1) { | |
32 | + switch (opt) { | |
33 | + case 'c': | |
34 | + role = 'c'; | |
35 | + break; | |
36 | + case 's': | |
37 | + break; | |
38 | + default: | |
39 | + printf("usage: %s [-cs]\n", argv[0]); | |
40 | + exit(1); | |
41 | + } | |
42 | + } | |
43 | + if (role == 's') { | |
44 | + server_run(); | |
45 | + } else { | |
46 | + client_run(); | |
47 | + } | |
48 | + return 0; | |
49 | +} | |
50 | + | |
51 | +/* | |
52 | + * register events of fd to epfd | |
53 | + */ | |
54 | +static void epoll_ctl_add(int epfd, int fd, uint32_t events) | |
55 | +{ | |
56 | + struct epoll_event ev; | |
57 | + ev.events = events; | |
58 | + ev.data.fd = fd; | |
59 | + if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1) { | |
60 | + perror("epoll_ctl()\n"); | |
61 | + exit(1); | |
62 | + } | |
63 | +} | |
64 | + | |
65 | +static void set_sockaddr(struct sockaddr_in *addr) | |
66 | +{ | |
67 | + bzero((char *)addr, sizeof(struct sockaddr_in)); | |
68 | + addr->sin_family = AF_INET; | |
69 | + addr->sin_addr.s_addr = INADDR_ANY; | |
70 | + addr->sin_port = htons(DEFAULT_PORT); | |
71 | +} | |
72 | + | |
73 | +static int setnonblocking(int sockfd) | |
74 | +{ | |
75 | + if (fcntl(sockfd, F_SETFD, fcntl(sockfd, F_GETFD, 0) | O_NONBLOCK) == | |
76 | + -1) { | |
77 | + return -1; | |
78 | + } | |
79 | + return 0; | |
80 | +} | |
81 | + | |
82 | +/* | |
83 | + * epoll echo server | |
84 | + */ | |
85 | +void server_run() | |
86 | +{ | |
87 | + int i; | |
88 | + int n; | |
89 | + int epfd; | |
90 | + int nfds; | |
91 | + int listen_sock; | |
92 | + int conn_sock; | |
93 | + int socklen; | |
94 | + char buf[BUF_SIZE]; | |
95 | + struct sockaddr_in srv_addr; | |
96 | + struct sockaddr_in cli_addr; | |
97 | + struct epoll_event events[MAX_EVENTS]; | |
98 | + | |
99 | + listen_sock = socket(AF_INET, SOCK_STREAM, 0); | |
100 | + | |
101 | + set_sockaddr(&srv_addr); | |
102 | + bind(listen_sock, (struct sockaddr *)&srv_addr, sizeof(srv_addr)); | |
103 | + | |
104 | + setnonblocking(listen_sock); | |
105 | + listen(listen_sock, MAX_CONN); | |
106 | + | |
107 | + epfd = epoll_create(1); | |
108 | + epoll_ctl_add(epfd, listen_sock, EPOLLIN | EPOLLOUT | EPOLLET); | |
109 | + | |
110 | + socklen = sizeof(cli_addr); | |
111 | + for (;;) { | |
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) - 1); | |
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) - 1)) > 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 | +} | |
200 | + | ... | ... |
fork1.c
0 → 100644
1 | +++ a/fork1.c | |
1 | +#include <stdio.h> | |
2 | +#include <stdlib.h> | |
3 | +#include <unistd.h> | |
4 | +#include <signal.h> | |
5 | +#include <sys/types.h> | |
6 | +#include <sys/wait.h> | |
7 | +#include <errno.h> | |
8 | + | |
9 | +int | |
10 | +main () | |
11 | +{ | |
12 | + pid_t res; | |
13 | + int status; | |
14 | + res = fork (); | |
15 | + if (res == 0) | |
16 | + { | |
17 | + printf ("Hello from child\n"); | |
18 | + sleep (1); | |
19 | + exit (1); | |
20 | + }; | |
21 | + if (res == -1) | |
22 | + perror ("fork"); | |
23 | + wait (&status); | |
24 | + if (WIFEXITED (status)) | |
25 | + printf ("Child exited normally with exit code %d\n", | |
26 | + WEXITSTATUS (status)); | |
27 | + else | |
28 | + printf ("Child exited abnormally\n"); | |
29 | + exit (0); | |
30 | +} | ... | ... |
fork2.c
0 → 100644
1 | +++ a/fork2.c | |
1 | +#include <stdio.h> | |
2 | +#include <stdlib.h> | |
3 | +#include <unistd.h> | |
4 | +#include <signal.h> | |
5 | +#include <sys/types.h> | |
6 | +#include <sys/wait.h> | |
7 | +#include <errno.h> | |
8 | + | |
9 | +int | |
10 | +main () | |
11 | +{ | |
12 | + pid_t res; | |
13 | + int status; | |
14 | + res = fork (); | |
15 | + if (res == 0) | |
16 | + { | |
17 | + printf ("Hello from child\n"); | |
18 | + sleep (1); | |
19 | + abort (); | |
20 | + }; | |
21 | + if (res == -1) | |
22 | + perror ("fork"); | |
23 | + wait (&status); | |
24 | + if (WIFEXITED (status)) | |
25 | + printf ("Child exited normally with exit code %d\n", | |
26 | + WEXITSTATUS (status)); | |
27 | + else | |
28 | + printf ("Child exited abnormally\n"); | |
29 | + exit (0); | |
30 | +} | ... | ... |
fork3.c
0 → 100644
1 | +++ a/fork3.c | |
1 | +#include <stdio.h> | |
2 | +#include <stdlib.h> | |
3 | +#include <unistd.h> | |
4 | +#include <signal.h> | |
5 | +#include <sys/types.h> | |
6 | +#include <sys/wait.h> | |
7 | +#include <errno.h> | |
8 | + | |
9 | +int | |
10 | +main () | |
11 | +{ | |
12 | + pid_t res; | |
13 | + int i; | |
14 | + res = fork (); | |
15 | + if (res == 0) | |
16 | + { | |
17 | + for (i = 0; i < 200; ++i) | |
18 | + { | |
19 | + printf ("Hello #%d from child\n", i); | |
20 | + } | |
21 | + abort (); | |
22 | + }; | |
23 | + if (res == -1) | |
24 | + perror ("fork"); | |
25 | + for (i = 0; i < 200; ++i) | |
26 | + { | |
27 | + printf ("Hello #%d from parent\n", i); | |
28 | + sleep (1); | |
29 | + }; | |
30 | + exit (0); | |
31 | +} | ... | ... |
fork4.c
0 → 100644
1 | +++ a/fork4.c | |
1 | +#include <stdio.h> | |
2 | +#include <stdlib.h> | |
3 | +#include <unistd.h> | |
4 | +#include <signal.h> | |
5 | +#include <sys/types.h> | |
6 | +#include <sys/wait.h> | |
7 | +#include <errno.h> | |
8 | + | |
9 | +int | |
10 | +main () | |
11 | +{ | |
12 | + pid_t res; | |
13 | + int status; | |
14 | + int i; | |
15 | + res = fork (); | |
16 | + if (res == 0) | |
17 | + { | |
18 | + for (i = 0; i < 200; ++i) | |
19 | + printf ("Hello #%d from child\n", i); | |
20 | + abort (); | |
21 | + }; | |
22 | + if (res == -1) | |
23 | + perror ("fork"); | |
24 | + for (i = 0; i < 200; ++i) | |
25 | + { | |
26 | + printf ("Hello #%d from parent\n", i); | |
27 | + if (waitpid (res, &status, WNOHANG) == res) | |
28 | + printf ("Child exited\n"); | |
29 | + sleep (1); | |
30 | + }; | |
31 | + exit (0); | |
32 | +} | ... | ... |
fork5.c
0 → 100644
1 | +++ a/fork5.c | |
1 | +#include <stdio.h> | |
2 | +#include <stdlib.h> | |
3 | +#include <unistd.h> | |
4 | +#include <signal.h> | |
5 | +#include <sys/types.h> | |
6 | +#include <sys/wait.h> | |
7 | +#include <errno.h> | |
8 | + | |
9 | +void | |
10 | +childsignal (int what) | |
11 | +{ | |
12 | + pid_t v; | |
13 | + int old_errno = errno; | |
14 | + printf ("New signal\n"); | |
15 | + while ((v = waitpid (-1, NULL, WNOHANG)) != 0 | |
16 | + && !(v == -1 && errno != EINTR)) | |
17 | + printf ("%d\n", v); | |
18 | + if (v == -1) | |
19 | + perror ("waitpid"); | |
20 | + printf ("Signal exit\n"); | |
21 | + errno = old_errno; | |
22 | +} | |
23 | + | |
24 | +int | |
25 | +main () | |
26 | +{ | |
27 | + int i; | |
28 | + struct sigaction sig; | |
29 | + sig.sa_handler = childsignal; | |
30 | + sigemptyset (&sig.sa_mask); | |
31 | + sig.sa_flags = SA_NOCLDSTOP; | |
32 | + sigaction (SIGCHLD, &sig, NULL); | |
33 | + for (i = 0; i < 200; i++) | |
34 | + { | |
35 | + pid_t res; | |
36 | + printf ("Starting child #%d\n", i); | |
37 | + res = fork (); | |
38 | + if (res == 0) | |
39 | + { | |
40 | + sleep (5); | |
41 | + exit (i + 1); | |
42 | + }; | |
43 | + if (res == -1) | |
44 | + perror ("fork"); | |
45 | + }; | |
46 | + for (i = 0; i < 360; i++) | |
47 | + sleep (1); | |
48 | + exit (0); | |
49 | +} | ... | ... |
fork6.c
0 → 100644
1 | +++ a/fork6.c | |
1 | +#include <stdio.h> | |
2 | +#include <stdlib.h> | |
3 | +#include <unistd.h> | |
4 | +#include <signal.h> | |
5 | +#include <sys/types.h> | |
6 | +#include <sys/wait.h> | |
7 | +#include <errno.h> | |
8 | + | |
9 | +int | |
10 | +main () | |
11 | +{ | |
12 | + int i; | |
13 | + signal (SIGCHLD, SIG_IGN); | |
14 | + for (i = 0; i < 200; i++) | |
15 | + { | |
16 | + pid_t res; | |
17 | + printf ("Starting child #%d\n", i); | |
18 | + res = fork (); | |
19 | + if (res == 0) | |
20 | + { | |
21 | + sleep (5); | |
22 | + exit (i + 1); | |
23 | + }; | |
24 | + if (res == -1) | |
25 | + perror ("fork"); | |
26 | + } | |
27 | + for (i = 0; i < 360; i++) | |
28 | + sleep (1); | |
29 | + exit (0); | |
30 | +} | ... | ... |
makefile
0 → 100644
1 | +++ a/makefile | |
1 | +CFLAGS=-ggdb -Wall -pedantic -D_REENTRANT | |
2 | + | |
3 | +%: %.c | |
4 | + gcc $(CFLAGS) $< -o $@ -lpthread | |
5 | + | |
6 | +EXECS = fork1 fork2 fork3 fork4 fork5 fork6 \ | |
7 | + netclient server1 server2 eintrc eintrs \ | |
8 | + threadsafe1 threadsafe2 threadsafe3 threadsafe4 \ | |
9 | + threadsafe5 threadsafe6 threadsafe7 \ | |
10 | + signal_example epoll1 epoll2 epoll3 epoll4 | |
11 | + | |
12 | +all: $(EXECS) | |
13 | + | |
14 | +fork1: fork1.c | |
15 | + | |
16 | +fork2: fork2.c | |
17 | + | |
18 | +fork3: fork3.c | |
19 | + | |
20 | +fork4: fork4.c | |
21 | + | |
22 | +fork5: fork5.c | |
23 | + | |
24 | +fork6: fork6.c | |
25 | + | |
26 | +netclient: netclient.c | |
27 | + | |
28 | +server1: server1.c | |
29 | + | |
30 | +server2: server2.c | |
31 | + | |
32 | +eintrc: eintrc.c | |
33 | + | |
34 | +eintrs: eintrs.c | |
35 | + | |
36 | +threadsafe1: threadsafe1.c | |
37 | + | |
38 | +threadsafe2: threadsafe2.c | |
39 | + | |
40 | +threadsafe3: threadsafe3.c | |
41 | + | |
42 | +threadsafe4: threadsafe4.c | |
43 | + | |
44 | +threadsafe5: threadsafe5.c | |
45 | + | |
46 | +threadsafe6: threadsafe6.c | |
47 | + | |
48 | +threadsafe7: threadsafe7.c | |
49 | + | |
50 | +signal_example: signal_example.c | |
51 | + | |
52 | +epoll1: epoll1.c | |
53 | + | |
54 | +epoll2: epoll2.c | |
55 | + | |
56 | +epoll3: epoll3.c | |
57 | + | |
58 | +epoll4: epoll4.c | |
59 | + | |
60 | +.PHONY: clean all | |
61 | + | |
62 | +clean: | |
63 | + rm -f $(EXECS) | ... | ... |
nc
0 → 100755
netclient.c
0 → 100644
1 | +++ a/netclient.c | |
1 | +/* Make the necessary includes and set up the variables. */ | |
2 | + | |
3 | +#include <sys/types.h> | |
4 | +#include <sys/socket.h> | |
5 | +#include <stdio.h> | |
6 | +#include <stdlib.h> | |
7 | +#include <netinet/in.h> | |
8 | +#include <arpa/inet.h> | |
9 | +#include <unistd.h> | |
10 | + | |
11 | +int | |
12 | +main () | |
13 | +{ | |
14 | + int sockfd; | |
15 | + socklen_t len; | |
16 | + struct sockaddr_in address; | |
17 | + int result; | |
18 | + char ch = 'A'; | |
19 | + | |
20 | + /* Create a socket for the client. */ | |
21 | + | |
22 | + sockfd = socket (AF_INET, SOCK_STREAM, 0); | |
23 | + | |
24 | + /* Name the socket, as agreed with the server. */ | |
25 | + | |
26 | + address.sin_family = AF_INET; | |
27 | + address.sin_addr.s_addr = inet_addr ("127.0.0.1"); | |
28 | + address.sin_port = htons (9734); | |
29 | + len = sizeof (address); | |
30 | + | |
31 | + /* Now connect our socket to the server's socket. */ | |
32 | + | |
33 | + result = connect (sockfd, (struct sockaddr *) &address, len); | |
34 | + | |
35 | + if (result == -1) | |
36 | + { | |
37 | + perror ("oops: netclient"); | |
38 | + exit (1); | |
39 | + } | |
40 | + | |
41 | + /* We can now read/write via sockfd. */ | |
42 | + | |
43 | + write (sockfd, &ch, 1); | |
44 | + read (sockfd, &ch, 1); | |
45 | + printf ("char from server = %c\n", ch); | |
46 | + close (sockfd); | |
47 | + exit (0); | |
48 | +} | ... | ... |
server1.c
0 → 100644
1 | +++ a/server1.c | |
1 | +#include <sys/types.h> | |
2 | +#include <sys/socket.h> | |
3 | +#include <stdio.h> | |
4 | +#include <netinet/in.h> | |
5 | +#include <signal.h> | |
6 | +#include <unistd.h> | |
7 | + | |
8 | +int | |
9 | +main () | |
10 | +{ | |
11 | + int server_sockfd, client_sockfd; | |
12 | + socklen_t server_len, client_len; | |
13 | + struct sockaddr_in server_address; | |
14 | + struct sockaddr_in client_address; | |
15 | + | |
16 | + server_sockfd = socket (AF_INET, SOCK_STREAM, 0); | |
17 | + | |
18 | + server_address.sin_family = AF_INET; | |
19 | + server_address.sin_addr.s_addr = htonl (INADDR_ANY); | |
20 | + server_address.sin_port = htons (9734); | |
21 | + server_len = sizeof (server_address); | |
22 | + bind (server_sockfd, (struct sockaddr *) &server_address, server_len); | |
23 | + | |
24 | + /* Create a connection queue and wait for clients. */ | |
25 | + | |
26 | + listen (server_sockfd, 5); | |
27 | + | |
28 | + while (1) | |
29 | + { | |
30 | + char ch; | |
31 | + | |
32 | + printf ("server waiting\n"); | |
33 | + | |
34 | + /* Accept connection. */ | |
35 | + | |
36 | + client_len = sizeof (client_address); | |
37 | + client_sockfd = accept (server_sockfd, | |
38 | + (struct sockaddr *) &client_address, | |
39 | + &client_len); | |
40 | + | |
41 | + /* We can now read/write to the client on client_sockfd. | |
42 | + The five second delay is just for this demonstration. */ | |
43 | + | |
44 | + read (client_sockfd, &ch, 1); | |
45 | + sleep (5); | |
46 | + ch++; | |
47 | + write (client_sockfd, &ch, 1); | |
48 | + close (client_sockfd); | |
49 | + } | |
50 | +} | ... | ... |
server2.c
0 → 100644
1 | +++ a/server2.c | |
1 | +#include <sys/types.h> | |
2 | +#include <sys/socket.h> | |
3 | +#include <stdio.h> | |
4 | +#include <stdlib.h> | |
5 | +#include <netinet/in.h> | |
6 | +#include <signal.h> | |
7 | +#include <unistd.h> | |
8 | + | |
9 | +int | |
10 | +main () | |
11 | +{ | |
12 | + int server_sockfd, client_sockfd; | |
13 | + socklen_t server_len, client_len; | |
14 | + struct sockaddr_in server_address; | |
15 | + struct sockaddr_in client_address; | |
16 | + | |
17 | + server_sockfd = socket (AF_INET, SOCK_STREAM, 0); | |
18 | + | |
19 | + server_address.sin_family = AF_INET; | |
20 | + server_address.sin_addr.s_addr = htonl (INADDR_ANY); | |
21 | + server_address.sin_port = htons (9734); | |
22 | + server_len = sizeof (server_address); | |
23 | + bind (server_sockfd, (struct sockaddr *) &server_address, server_len); | |
24 | + | |
25 | + /* Create a connection queue, ignore child exit details and wait for clients. */ | |
26 | + | |
27 | + listen (server_sockfd, 5); | |
28 | + | |
29 | + signal (SIGCHLD, SIG_IGN); | |
30 | + | |
31 | + while (1) | |
32 | + { | |
33 | + char ch; | |
34 | + | |
35 | + printf ("server waiting\n"); | |
36 | + | |
37 | + /* Accept connection. */ | |
38 | + | |
39 | + client_len = sizeof (client_address); | |
40 | + client_sockfd = accept (server_sockfd, | |
41 | + (struct sockaddr *) &client_address, | |
42 | + &client_len); | |
43 | + | |
44 | + /* Fork to create a process for this client and perform a test to see | |
45 | + whether we're the parent or the child. */ | |
46 | + | |
47 | + if (fork () == 0) | |
48 | + { | |
49 | + | |
50 | + /* If we're the child, we can now read/write to the client on client_sockfd. | |
51 | + The five second delay is just for this demonstration. */ | |
52 | + | |
53 | + read (client_sockfd, &ch, 1); | |
54 | + sleep (5); | |
55 | + ch++; | |
56 | + write (client_sockfd, &ch, 1); | |
57 | + close (client_sockfd); | |
58 | + exit (0); | |
59 | + } | |
60 | + | |
61 | + /* Otherwise, we must be the parent and our work for this client is finished. */ | |
62 | + | |
63 | + else | |
64 | + { | |
65 | + close (client_sockfd); | |
66 | + } | |
67 | + } | |
68 | +} | ... | ... |
signal_example.c
0 → 100644
1 | +++ a/signal_example.c | |
1 | +#include <stdio.h> | |
2 | +#include <stdlib.h> | |
3 | +#include <unistd.h> | |
4 | +#include <signal.h> | |
5 | +#include <sys/types.h> | |
6 | +#include <sys/wait.h> | |
7 | +#include <errno.h> | |
8 | + | |
9 | +void | |
10 | +signal_handler (int what) | |
11 | +{ | |
12 | + printf ("Signal number: %d\n", what); | |
13 | + printf ("Waiting for signal ... [send SIGKILL to abort]\n"); | |
14 | +} | |
15 | + | |
16 | +int | |
17 | +main () | |
18 | +{ | |
19 | + struct sigaction sig; | |
20 | + sig.sa_handler = signal_handler; | |
21 | + sigemptyset (&sig.sa_mask); | |
22 | + sig.sa_flags = SA_NOCLDSTOP; | |
23 | + sigaction (SIGHUP, &sig, NULL); | |
24 | + sigaction (SIGINT, &sig, NULL); | |
25 | + sigaction (SIGQUIT, &sig, NULL); | |
26 | + sigaction (SIGABRT, &sig, NULL); | |
27 | + sigaction (SIGALRM, &sig, NULL); | |
28 | + sigaction (SIGTERM, &sig, NULL); | |
29 | + sigaction (SIGUSR1, &sig, NULL); | |
30 | + sigaction (SIGUSR2, &sig, NULL); | |
31 | + | |
32 | + printf ("PID: %d\n", getpid ()); | |
33 | + printf ("Waiting for signal ... [send SIGKILL to abort]\n"); | |
34 | + | |
35 | + while (1) | |
36 | + sleep (1); | |
37 | + | |
38 | + exit (0); | |
39 | +} | ... | ... |
testnc
0 → 100755
threadsafe1.c
0 → 100644
1 | +++ a/threadsafe1.c | |
1 | +#include <stdio.h> | |
2 | +#include <stdlib.h> | |
3 | +#include <pthread.h> | |
4 | + | |
5 | +char * | |
6 | +unsafe_itoa (int number) | |
7 | +{ | |
8 | + static char buf[16]; | |
9 | + int i = 0, j; | |
10 | + do | |
11 | + { | |
12 | + buf[i++] = number % 10 + '0'; | |
13 | + number /= 10; | |
14 | + } | |
15 | + while (number); | |
16 | + buf[i] = 0; | |
17 | + for (j = 0; j < i / 2; j++) | |
18 | + { | |
19 | + char c = buf[j]; | |
20 | + buf[j] = buf[i - j - 1]; | |
21 | + buf[i - j - 1] = c; | |
22 | + }; | |
23 | + return buf; | |
24 | +} | |
25 | + | |
26 | + | |
27 | +void * | |
28 | +thread (void *param) | |
29 | +{ | |
30 | + int start = *((int *) (param)); | |
31 | + int i; | |
32 | + printf("Hello from thread %d\n",start); | |
33 | + for (i = 0; i < 10000; i++) | |
34 | + printf ("%d %s\n", i + start, unsafe_itoa (i + start)); | |
35 | + pthread_exit (param); | |
36 | +} | |
37 | + | |
38 | +int | |
39 | +main (int argc, char *argv[]) | |
40 | +{ | |
41 | + pthread_t t1, t2; | |
42 | + pthread_attr_t attr; | |
43 | + int a, b; | |
44 | + void *retval; | |
45 | + a = 0; | |
46 | + pthread_attr_init (&attr); | |
47 | + pthread_create (&t1, &attr, thread, &a); | |
48 | + if (argc > 1) | |
49 | + { | |
50 | + b = 10000; | |
51 | + pthread_create (&t2, &attr, thread, &b); | |
52 | + pthread_join (t2, &retval); | |
53 | + }; | |
54 | + pthread_join (t1, &retval); | |
55 | + exit (0); | |
56 | +} | ... | ... |
threadsafe2.c
0 → 100644
1 | +++ a/threadsafe2.c | |
1 | +#include <stdio.h> | |
2 | +#include <stdlib.h> | |
3 | +#include <pthread.h> | |
4 | + | |
5 | +char * | |
6 | +safe_itoa (int number, char *buf) | |
7 | +{ | |
8 | + int i = 0, j; | |
9 | + do | |
10 | + { | |
11 | + buf[i++] = number % 10 + '0'; | |
12 | + number /= 10; | |
13 | + } | |
14 | + while (number); | |
15 | + buf[i] = 0; | |
16 | + for (j = 0; j < i / 2; j++) | |
17 | + { | |
18 | + char c = buf[j]; | |
19 | + buf[j] = buf[i - j - 1]; | |
20 | + buf[i - j - 1] = c; | |
21 | + }; | |
22 | + return buf; | |
23 | +} | |
24 | + | |
25 | + | |
26 | +void * | |
27 | +thread (void *param) | |
28 | +{ | |
29 | + char buf[16]; | |
30 | + int start = *((int *) (param)); | |
31 | + int i; | |
32 | + printf ("Hello from thread %d\n", start); | |
33 | + for (i = 0; i < 10000; i++) | |
34 | + printf ("%d %s\n", i + start, safe_itoa (i + start, buf)); | |
35 | + pthread_exit (param); | |
36 | +} | |
37 | +int | |
38 | +main (int argc, char *argv[]) | |
39 | +{ | |
40 | + pthread_t t1, t2; | |
41 | + pthread_attr_t attr; | |
42 | + int a, b; | |
43 | + void *retval; | |
44 | + a = 0; | |
45 | + pthread_attr_init (&attr); | |
46 | + pthread_create (&t1, &attr, thread, &a); | |
47 | + if (argc > 1) | |
48 | + { | |
49 | + b = 10000; | |
50 | + pthread_create (&t2, &attr, thread, &b); | |
51 | + pthread_join (t2, &retval); | |
52 | + }; | |
53 | + pthread_join (t1, &retval); | |
54 | + exit (0); | |
55 | +} | ... | ... |
threadsafe3.c
0 → 100644
1 | +++ a/threadsafe3.c | |
1 | +#include <stdio.h> | |
2 | +#include <stdlib.h> | |
3 | +#include <pthread.h> | |
4 | + | |
5 | +char * | |
6 | +unsafe_itoa (int number) | |
7 | +{ | |
8 | + static char buf[16]; | |
9 | + int i = 0, j; | |
10 | + do | |
11 | + { | |
12 | + buf[i++] = number % 10 + '0'; | |
13 | + number /= 10; | |
14 | + } | |
15 | + while (number); | |
16 | + buf[i] = 0; | |
17 | + for (j = 0; j < i / 2; j++) | |
18 | + { | |
19 | + char c = buf[j]; | |
20 | + buf[j] = buf[i - j - 1]; | |
21 | + buf[i - j - 1] = c; | |
22 | + }; | |
23 | + return buf; | |
24 | +} | |
25 | + | |
26 | +pthread_mutex_t itoa_mutex; | |
27 | + | |
28 | +void * | |
29 | +thread (void *param) | |
30 | +{ | |
31 | + int start = *((int *) (param)); | |
32 | + int i; | |
33 | + printf("Hello from thread %d\n",start); | |
34 | + for (i = 0; i < 10000; i++) | |
35 | + { | |
36 | + pthread_mutex_lock(&itoa_mutex); | |
37 | + printf ("%d %s\n", i + start, unsafe_itoa (i + start)); | |
38 | + pthread_mutex_unlock(&itoa_mutex); | |
39 | + } | |
40 | + pthread_exit (param); | |
41 | +} | |
42 | + | |
43 | +int | |
44 | +main (int argc, char *argv[]) | |
45 | +{ | |
46 | + pthread_t t1, t2; | |
47 | + pthread_attr_t attr; | |
48 | + int a, b; | |
49 | + void *retval; | |
50 | + a = 0; | |
51 | + pthread_mutex_init(&itoa_mutex,NULL); | |
52 | + pthread_attr_init (&attr); | |
53 | + pthread_create (&t1, &attr, thread, &a); | |
54 | + if (argc > 1) | |
55 | + { | |
56 | + b = 10000; | |
57 | + pthread_create (&t2, &attr, thread, &b); | |
58 | + pthread_join (t2, &retval); | |
59 | + }; | |
60 | + pthread_join (t1, &retval); | |
61 | + pthread_mutex_destroy(&itoa_mutex); | |
62 | + exit (0); | |
63 | +} | ... | ... |
threadsafe4.c
0 → 100644
1 | +++ a/threadsafe4.c | |
1 | +#include <stdio.h> | |
2 | +#include <stdlib.h> | |
3 | +#include <pthread.h> | |
4 | + | |
5 | +int c; | |
6 | + | |
7 | +void * | |
8 | +thread (void *param) | |
9 | +{ | |
10 | + int i; | |
11 | + for (i = 0; i < 10000; i++) | |
12 | + { | |
13 | + c=c*123413123+7;; | |
14 | + } | |
15 | + pthread_exit (param); | |
16 | +} | |
17 | + | |
18 | +int | |
19 | +main (int argc, char *argv[]) | |
20 | +{ | |
21 | + pthread_t t1, t2; | |
22 | + pthread_attr_t attr; | |
23 | + int a, b; | |
24 | + void *retval; | |
25 | + a = 0; | |
26 | + pthread_attr_init (&attr); | |
27 | + pthread_create (&t1, &attr, thread, &a); | |
28 | + if (argc > 1) | |
29 | + { | |
30 | + b = 10000; | |
31 | + pthread_create (&t2, &attr, thread, &b); | |
32 | + pthread_join (t2, &retval); | |
33 | + }; | |
34 | + pthread_join (t1, &retval); | |
35 | + printf("c=%d\n",c); | |
36 | + exit (0); | |
37 | +} | ... | ... |
threadsafe5.c
0 → 100644
1 | +++ a/threadsafe5.c | |
1 | +#include <stdio.h> | |
2 | +#include <stdlib.h> | |
3 | +#include <pthread.h> | |
4 | + | |
5 | +int c; | |
6 | + | |
7 | +pthread_mutex_t itoa_mutex; | |
8 | + | |
9 | +void * | |
10 | +thread (void *param) | |
11 | +{ | |
12 | + int i; | |
13 | + for (i = 0; i < 10000; i++) | |
14 | + { | |
15 | + pthread_mutex_lock(&itoa_mutex); | |
16 | + c=c*123413123+7;; | |
17 | + pthread_mutex_unlock(&itoa_mutex); | |
18 | + } | |
19 | + pthread_exit (param); | |
20 | +} | |
21 | + | |
22 | +int | |
23 | +main (int argc, char *argv[]) | |
24 | +{ | |
25 | + pthread_t t1, t2; | |
26 | + pthread_attr_t attr; | |
27 | + int a, b; | |
28 | + void *retval; | |
29 | + a = 0; | |
30 | + pthread_mutex_init(&itoa_mutex,NULL); | |
31 | + pthread_attr_init (&attr); | |
32 | + pthread_create (&t1, &attr, thread, &a); | |
33 | + if (argc > 1) | |
34 | + { | |
35 | + b = 10000; | |
36 | + pthread_create (&t2, &attr, thread, &b); | |
37 | + pthread_join (t2, &retval); | |
38 | + }; | |
39 | + pthread_join (t1, &retval); | |
40 | + pthread_mutex_destroy(&itoa_mutex); | |
41 | + printf("c=%d\n",c); | |
42 | + exit (0); | |
43 | +} | ... | ... |
threadsafe6.c
0 → 100644
1 | +++ a/threadsafe6.c | |
1 | +#include <stdio.h> | |
2 | +#include <stdlib.h> | |
3 | +#include <pthread.h> | |
4 | + | |
5 | +volatile int c; | |
6 | + | |
7 | +pthread_mutex_t itoa_mutex; | |
8 | + | |
9 | +void * | |
10 | +thread (void *param) | |
11 | +{ | |
12 | + int i; | |
13 | + for (i = 0; i < 10000; i++) | |
14 | + { | |
15 | + pthread_mutex_lock(&itoa_mutex); | |
16 | + c=c*123413123+7;; | |
17 | + pthread_mutex_unlock(&itoa_mutex); | |
18 | + } | |
19 | + pthread_exit (param); | |
20 | +} | |
21 | + | |
22 | +int | |
23 | +main (int argc, char *argv[]) | |
24 | +{ | |
25 | + pthread_t t1, t2; | |
26 | + pthread_attr_t attr; | |
27 | + int a, b; | |
28 | + void *retval; | |
29 | + a = 0; | |
30 | + pthread_mutex_init(&itoa_mutex,NULL); | |
31 | + pthread_attr_init (&attr); | |
32 | + pthread_create (&t1, &attr, thread, &a); | |
33 | + if (argc > 1) | |
34 | + { | |
35 | + b = 10000; | |
36 | + pthread_create (&t2, &attr, thread, &b); | |
37 | + pthread_join (t2, &retval); | |
38 | + }; | |
39 | + pthread_join (t1, &retval); | |
40 | + pthread_mutex_destroy(&itoa_mutex); | |
41 | + printf("c=%d\n",c); | |
42 | + exit (0); | |
43 | +} | ... | ... |
threadsafe7.c
0 → 100644
1 | +++ a/threadsafe7.c | |
1 | +#include <stdio.h> | |
2 | +#include <stdlib.h> | |
3 | +#include <pthread.h> | |
4 | + | |
5 | +volatile int c; | |
6 | + | |
7 | +void * | |
8 | +thread (void *param) | |
9 | +{ | |
10 | + int i; | |
11 | + for (i = 0; i < 10000; i++) | |
12 | + { | |
13 | + c=c*123413123+7;; | |
14 | + } | |
15 | + pthread_exit (param); | |
16 | +} | |
17 | + | |
18 | +int | |
19 | +main (int argc, char *argv[]) | |
20 | +{ | |
21 | + pthread_t t1, t2; | |
22 | + pthread_attr_t attr; | |
23 | + int a, b; | |
24 | + void *retval; | |
25 | + a = 0; | |
26 | + pthread_attr_init (&attr); | |
27 | + pthread_create (&t1, &attr, thread, &a); | |
28 | + if (argc > 1) | |
29 | + { | |
30 | + b = 10000; | |
31 | + pthread_create (&t2, &attr, thread, &b); | |
32 | + pthread_join (t2, &retval); | |
33 | + }; | |
34 | + pthread_join (t1, &retval); | |
35 | + printf("c=%d\n",c); | |
36 | + exit (0); | |
37 | +} | ... | ... |