一.实验目的
(1) 在理解进程的概念及其生命周期和状态转换过程的基础上,进行进程相关编程;
(2) 在理解进程间通信的基本原理的基础上,编程实现进程间通信。
二.实验内容
(1) 在Linux中利用fork()在父进程A中创建一个子进程B,再在子进程A中创建一个子进程C,在3个进程中都要编写适当的语句模拟进程的工作。
(2) 创建子进程时将复制父进程的所有内容,此时的复制对象也包含套接字文件描述符。编写程序验证复制的文件描述符整数值是否与原文件描述符整数值相同。
(3) 如果在未注册SIGINT信号的情况下输入Ctrl+C,将由操作系统默认的事件处理器终止程序。但如果直接注册Ctrl+C信号的处理器,则程序不会终止,而是调用程序员指定的事件处理器。编写注册处理函数的程序,完成如下功能:
“输入Ctrl+C时,询问是否确定退出程序,输入Y则终止程序。”
另外,编写程序使其每隔1秒输出简单字符串,并适用于上述时间处理器注册代码。
(4) 利用fork()实现并发服务器,且让客户端的读写操作由两个进程分别处理。
(5) 编写程序实现进程间通信,使2个进程相互交换3次字符串。当然,这2个进程应具有父子关系,各位可指定任意字符串。
三.实验过程
(1)实验代码;
/*进入子进程创建子进程*/#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <signal.h>#include <sys/wait.h>int ossion(); //函数的申明int flag = 0; //全局变量int main(int argc, char **argv){ossion();return 0;}int ossion(){flag += 1;if(flag < 6) //退出条件,总共递归五次{pid_t pid;pid = fork();if(pid == 0){printf(\"son pid :%d\\n\",getpid());ossion(); //子进程创建成功,再次进入递归return 0;}waitpid(pid,NULL,WUNTRACED);}return 0;}
结果:
(2)实现代码:
Fork1.c:#include <stdio.h>#include <unistd.h>#include <sys/socket.h>int main(int argc, char *argv[]){pid_t pid;int sockfd=socket(PF_INET, SOCK_STREAM, 0);pid=fork();if(pid==0)printf(\"Child sock fd: [%d] \\n\\n\", sockfd);elseprintf(\"Parent sock fd: [%d] \\n\\n\", sockfd);return 0;}
结果:
(3)实现代码
Fork2.c:#include <stdio.h>#include <stdlib.h>#include <signal.h>void ctrl_handler(int sig);int main(int argc, char *argv[]){struct sigaction act;act.sa_handler=ctrl_handler;sigemptyset(&act.sa_mask);act.sa_flags=0;sigaction(SIGINT, &act, 0);while(1){sleep(1);puts(\"Have a nice day~\");}return 0;}void ctrl_handler(int sig){char ex;fputs(\"Do you want exit(Y to exit)? \", stdout);scanf(\"%c\", &ex);if(ex==\'y\' || ex==\'Y\')exit(1);}
结果:
(4)实现代码:
Server.c:#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <signal.h>#include <sys/wait.h>#include <arpa/inet.h>#include <sys/socket.h>#define BUF_SIZE 30void error_handling(char *message);void read_childproc(int sig);int main(int argc, char *argv[]){int serv_sock, clnt_sock;struct sockaddr_in serv_adr, clnt_adr;pid_t pid;struct sigaction act;socklen_t adr_sz;int str_len, state;char buf[BUF_SIZE];if(argc!=2) {printf(\"Usage : %s <port>\\n\", argv[0]);exit(1);}act.sa_handler=read_childproc;sigemptyset(&act.sa_mask);act.sa_flags=0;state=sigaction(SIGCHLD, &act, 0);serv_sock=socket(PF_INET, SOCK_STREAM, 0);memset(&serv_adr, 0, sizeof(serv_adr));serv_adr.sin_family=AF_INET;serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);serv_adr.sin_port=htons(atoi(argv[1]));if(bind(serv_sock, (struct sockaddr*) &serv_adr, sizeof(serv_adr))==-1)error_handling(\"bind() error\");if(listen(serv_sock, 5)==-1)error_handling(\"listen() error\");while(1){adr_sz=sizeof(clnt_adr);clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_adr, &adr_sz);if(clnt_sock==-1)continue;elseputs(\"new client connected...\");pid=fork();if(pid==-1){close(clnt_sock);continue;}if(pid==0){close(serv_sock);while((str_len=read(clnt_sock, buf, BUF_SIZE))!=0)write(clnt_sock, buf, str_len);close(clnt_sock);puts(\"client disconnected...\");return 0;}elseclose(clnt_sock);}close(serv_sock);return 0;}void read_childproc(int sig){pid_t pid;int status;pid=waitpid(-1, &status, WNOHANG);printf(\"removed proc id: %d \\n\", pid);}void error_handling(char *message){fputs(message, stderr);fputc(\'\\n\', stderr);exit(1);}Client.c:#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <arpa/inet.h>#include <sys/socket.h>#define BUF_SIZE 1024void error_handling(char *message);int main(int argc, char *argv[]){int sock;char message[BUF_SIZE];int str_len;struct sockaddr_in serv_adr;if(argc!=3) {printf(\"Usage : %s <IP> <port>\\n\", argv[0]);exit(1);}sock=socket(PF_INET, SOCK_STREAM, 0);if(sock==-1)error_handling(\"socket() error\");memset(&serv_adr, 0, sizeof(serv_adr));serv_adr.sin_family=AF_INET;serv_adr.sin_addr.s_addr=inet_addr(argv[1]);serv_adr.sin_port=htons(atoi(argv[2]));if(connect(sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1)error_handling(\"connect() error!\");elseputs(\"Connected...........\");while(1){fputs(\"Input message(Q to quit): \", stdout);fgets(message, BUF_SIZE, stdin);if(!strcmp(message,\"q\\n\") || !strcmp(message,\"Q\\n\"))break;write(sock, message, strlen(message));str_len=read(sock, message, BUF_SIZE-1);message[str_len]=0;printf(\"Message from server: %s\", message);}close(sock);return 0;}void error_handling(char *message){fputs(message, stderr);fputc(\'\\n\', stderr);exit(1);}
结果:
(5)实现代码:
Fork_message.c:#include <stdio.h>#include <string.h>#include <unistd.h>#define BUF_SIZE 30int main(int argc, char *argv[]){int fds1[2], fds2[2];char str1[]=\"Do you like coffee?\";char str2[]=\"I like coffee\";char str3[]=\"I like bread\";char * str_arr[]={str1, str2, str3};char buf[BUF_SIZE];pid_t pid;int i;pipe(fds1), pipe(fds2);pid=fork();if(pid==0){for(i=0; i<3; i++){write(fds1[1], str_arr[i], strlen(str_arr[i])+1);read(fds2[0], buf, BUF_SIZE);printf(\"Child proc output: %s \\n\", buf);}}else{for(i=0; i<3; i++){read(fds1[0], buf, BUF_SIZE);printf(\"Parent proc output: %s \\n\", buf);write(fds2[1], str_arr[i], strlen(str_arr[i])+1);}}return 0;}
结果: