四、基于多任务的并发服务器( 四 )


函数在UNIX系列的不同操作系统中可能存在区别,但函数完全相同 。
#include /* Get and/or set the action for signal SIG.*/extern int sigaction (int __sig, const struct sigaction *__restrict __act,struct sigaction *__restrict __oact) __THROW;
结构体如下:
typedef void (*__sighandler_t) (int);struct sigaction{/* Signal handler.*/#if defined __USE_POSIX199309 || defined __USE_XOPEN_EXTENDEDunion{/* Used if SA_SIGINFO is not set.*/__sighandler_t sa_handler;/* Used if SA_SIGINFO is set.*/void (*sa_sigaction) (int, siginfo_t *, void *);}__sigaction_handler;# define sa_handler__sigaction_handler.sa_handler# define sa_sigaction__sigaction_handler.sa_sigaction#else__sighandler_t sa_handler;#endif/* Additional set of signals to be blocked.*/__sigset_t sa_mask;/* Special flags.*/int sa_flags;/* Restore handler.*/void (*sa_restorer) (void);};
成员保存信号处理函数的指针值,和的所有位均初始化为0即可 。可以使用函数将成员的所有位初始化为0
1 #include2 #include 3 #include45 void timeout(int sig) { 6if(sig == SIGALRM) 7puts("Time out!"); 8alarm(2); 9 }10 int main(int argc, char *argv[]) {11int i;12struct sigaction act;13act.sa_handler = timeout;14sigemptyset(&act.sa_mask);15act.sa_flags = 0;16sigaction(SIGALRM, &act, 0);17alarm(2);18for(i = 0; i < 3; i ++) {19puts("wait...");20sleep(100);21}22return 0;23 }
View Code

四、基于多任务的并发服务器

文章插图
3、利用信号处理技术消灭僵尸进程
子进程在终止时会产生信号,通过这点,利用信号处理机制就能消灭僵尸进程了 。
1 #include2 #include3 #include 4 #include5 #include67 void read_childproc(int sig) { 8int status; 9pid_t id = waitpid(-1, &status, WNOHANG);10if(WIFEXITED(status)) {11printf("Removed proc id: %d \n",id);12printf("Child send: %d \n",WEXITSTATUS(status));13}14 }15 16 int main(int argc, char *argv[]) {17pid_t pid;18struct sigaction act;19act.sa_handler = read_childproc;20sigemptyset(&act.sa_mask);21act.sa_flags = 0;22sigaction(SIGCHLD, &act, 0);23 24pid = fork();25if(pid == 0) {26puts("Hi! I'm child process");27sleep(10);28return 12;29} else {30printf("Child proc id: %d \n", pid);31pid = fork();32if(pid == 0) {33puts("Hi! I'm child process");34sleep(9);//如果睡眠十秒的话有可能只消灭一个僵尸进程,然后两个进程同学调用一个函数 (猜的!!!)35exit(24);36} else{37int i;38printf("Child proc id: %d \n", pid);39for(i = 0; i < 5; i ++) {40puts("wait...");41sleep(5);42}43}44}45return 0;46 }
四、基于多任务的并发服务器

文章插图
可以看出,子进程并未变成僵尸进程 。
四、基于多任务的并发服务器 1、基于进程的并发服务器模型
并发服务器模型使其可以同时多个客户端提供服务 。
第一阶段:回声服务器(父进程)通过调用函数受理连接请求 。
第二阶段:此时获取的套接字文件描述符创建并传递给子进程 。
第三阶段:子进程利用传递来的文件描述符提供服务 。
1 #include2 #include3 #include 4 #include 5 #include6 #include7 #include8 #include9 10 #define BUF_SIZE 3011 void error_handling(const char *message);12 void read_childproc(int sig);13 14 int main(int argc, char *argv[]) {15int serv_sock, clnt_sock;16struct sockaddr_in serv_adr, clnt_adr;17 18pid_t pid;19struct sigaction act;20socklen_t addr_sz;21int str_len,state;22char buf[BUF_SIZE];23if(argc != 2) {24printf("Usage: %s\n",argv[0]);25exit(1);26}27 28act.sa_handler = read_childproc;29sigemptyset(&act.sa_mask);30act.sa_flags = 0;31state = sigaction(SIGCHLD, &act, 0);32serv_sock = socket(AF_INET, SOCK_STREAM, 0);33memset(&serv_adr, 0, sizeof(serv_adr));34serv_adr.sin_family = AF_INET;35serv_adr.sin_addr.s_addr = htonl(INADDR_ANY);36serv_adr.sin_port = htons(atoi(argv[1]));37 38if(bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr)) == -1)39error_handling("bin() error");40 41if(listen(serv_sock, 5) == -1)42error_handling("listen() error");43 44while (1) {45addr_sz = sizeof(clnt_adr);46clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_adr, &addr_sz);47if(clnt_sock == -1)48continue;49else50puts("new client connected...");51pid = fork();52if(pid == -1) {53close(clnt_sock);54continue;55}56if(pid == 0) {57close(serv_sock);58while ((str_len = read(clnt_sock, buf, BUF_SIZE)) != 0)59write(clnt_sock, buf, str_len);60close(clnt_sock);61puts("client disconnected");62return 0;63} else64close(clnt_sock);65}66close(serv_sock);67return 0;68 }69 void read_childproc(int sig) {70pid_t pid;71int status;72pid = waitpid(-1, &status, WNOHANG);73printf("remove proc id: %d \n", pid);74 }75 76 void error_handling(const char *message) {77fputs(message, stderr);78fputc('\n', stderr);79exit(1);80 }