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 | +} |