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