• 《TCP/IP网络编程》阅读笔记--进程间通信


    目录

    1--进程间通信

    2--pipe()函数

    3--代码实例

    3-1--pipe1.c

    3-2--pipe2.c

    3-3--pipe3.c

    3-4--保存信息的回声服务器端


    1--进程间通信

            为了实现进程间通信,使得两个不同的进程间可以交换数据,操作系统必须提供两个进程可以同时访问的内存空间;

            为了完成进程间通信,需要创建管道(pipe);管道并非属于进程的资源,而是属于操作系统;

    2--pipe()函数

    1. #include
    2. int pipe(int filedes[2]);
    3. // 成功时返回0,失败时返回-1
    4. // filedes[0] 通过管道接收数据时使用的文件描述符,即管道出口
    5. // filedes[1] 通过管道传输数据时使用的文件描述符,即管道入口

    3--代码实例

    3-1--pipe1.c

            子进程从管道入口写数据,父进程从管道出口读数据;

    1. // gcc pipe1.c -o pipe
    2. // ./pipe
    3. #include
    4. #include
    5. #define BUF_SIZE 30
    6. int main(int argc, char *argv[]){
    7. int fds[2];
    8. char str[] = "Who are you?";
    9. char buf[BUF_SIZE];
    10. __pid_t pid;
    11. pipe(fds); // 创建管道
    12. pid = fork();
    13. if(pid == 0){ // 子进程执行区域
    14. write(fds[1], str, sizeof(str)); // 向管道入口写数据
    15. }
    16. else{ // 父进程执行区域
    17. read(fds[0], buf, BUF_SIZE); // 向管道出口读数据
    18. puts(buf);
    19. }
    20. return 0;
    21. }

    3-2--pipe2.c

            利用一个管道实现父进程与子进程的双向通信;

    1. // gcc pipe2.c -o pipe2
    2. // ./pipe2
    3. #include
    4. #include
    5. #define BUF_SIZE 30
    6. int main(int argc, char *argv[]){
    7. int fds[2];
    8. char str1[] = "Who are you?";
    9. char str2[] = "Thank you for your message";
    10. char buf[BUF_SIZE];
    11. __pid_t pid;
    12. pipe(fds); // 创建管道
    13. pid = fork();
    14. if(pid == 0){ // 子进程执行区域
    15. write(fds[1], str1, sizeof(str1));
    16. sleep(2); // sleep的作用是防止子线程写的数据被子线程自身读取了,导致父进程一直等待
    17. read(fds[0], buf, BUF_SIZE);
    18. printf("Child proc output: %s \n", buf);
    19. }
    20. else{ // 父进程执行区域
    21. read(fds[0], buf, BUF_SIZE);
    22. printf("Parent proc output: %s \n", buf);
    23. write(fds[1], str2, sizeof(str2));
    24. sleep(3);
    25. }
    26. return 0;
    27. }

    3-3--pipe3.c

            利用两个管道实现父进程与子进程的双向通信,其中收发数据在不同的管道上进行;

    1. // gcc pipe3.c -o pipe3
    2. // ./pipe3
    3. #include
    4. #include
    5. #define BUF_SIZE 30
    6. int main(int argc, char *argv[]){
    7. int fds1[2], fds2[2];
    8. char str1[] = "Who are you?";
    9. char str2[] = "Thank you for your message";
    10. char buf[BUF_SIZE];
    11. __pid_t pid;
    12. pipe(fds1), pipe(fds2); // 创建管道
    13. pid = fork();
    14. if(pid == 0){ // 子进程执行区域
    15. write(fds1[1], str1, sizeof(str1)); // 通过管道1写数据
    16. read(fds2[0], buf, BUF_SIZE); // 通过管道2读数据
    17. printf("Child proc output: %s \n", buf);
    18. }
    19. else{ // 父进程执行区域
    20. read(fds1[0], buf, BUF_SIZE); // 通过管道1读数据
    21. printf("Parent proc output: %s \n", buf);
    22. write(fds2[1], str2, sizeof(str2)); // 通过管道2写数据
    23. sleep(3);
    24. }
    25. return 0;
    26. }

    3-4--保存信息的回声服务器端

            服务器端创建两个进程,一个进程负责与客户端进行通信,将客户端发来的数据通过管道入口写到管道中;另一个进程负责从管道出口中读取数据,并把读取的数据保存在文件中;

            具体可运行代码参考:Chapter11

    1. // gcc echo_storeserv.c -o echo_storeserv
    2. // ./echo_storeserv 9190
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #define BUF_SIZE 30
    12. void error_handling(char *message){
    13. fputs(message, stderr);
    14. fputc('\n', stderr);
    15. exit(1);
    16. }
    17. void read_childproc(int sig){
    18. __pid_t pid;
    19. int status;
    20. pid = waitpid(-1, &status, WNOHANG);
    21. printf("remove proc id: %d \n", pid);
    22. }
    23. int main(int argc, char* argv[]){
    24. int serv_sock, clnt_sock;
    25. struct sockaddr_in serv_adr, clnt_adr;
    26. int fds[2];
    27. __pid_t pid;
    28. struct sigaction act; // 信号
    29. socklen_t adr_sz;
    30. int str_len, state;
    31. char buf[BUF_SIZE];
    32. if(argc != 2){
    33. printf("Usage : %s \n", argv[0]);
    34. exit(1);
    35. }
    36. act.sa_handler = read_childproc; //设置信号处理函数
    37. sigemptyset(&act.sa_mask);
    38. act.sa_flags = 0;
    39. state = sigaction(SIGCHLD, &act, 0);
    40. serv_sock = socket(PF_INET, SOCK_STREAM, 0); // 创建 tcp socket
    41. memset(&serv_adr, 0, sizeof(serv_adr));
    42. serv_adr.sin_family = AF_INET;
    43. serv_adr.sin_addr.s_addr = htonl(INADDR_ANY);
    44. serv_adr.sin_port = htons(atoi(argv[1]));
    45. if(bind(serv_sock, (struct sockaddr*) &serv_adr, sizeof(serv_adr)) == -1){
    46. error_handling("bind() error");
    47. }
    48. if(listen(serv_sock, 5) == -1){
    49. error_handling("listen() error");
    50. }
    51. pipe(fds);
    52. pid = fork();
    53. if(pid == 0){ // 子进程执行区域
    54. FILE* fp = fopen("echomsg.txt", "wt");
    55. char msgbuf[BUF_SIZE];
    56. int i, len;
    57. for(i = 0; i < 10; i++){
    58. len = read(fds[0], msgbuf, BUF_SIZE);
    59. fwrite((void*)msgbuf, 1, len, fp);
    60. }
    61. fclose(fp);
    62. return 0;
    63. }
    64. while(1){
    65. adr_sz = sizeof(clnt_adr);
    66. clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_adr, &adr_sz);
    67. if(clnt_sock == -1){
    68. continue;
    69. }
    70. else{
    71. puts("new client connected...");
    72. }
    73. pid = fork();
    74. if(pid == 0){
    75. close(serv_sock);
    76. while((str_len = read(clnt_sock, buf, BUF_SIZE)) != 0){
    77. write(clnt_sock, buf, str_len);
    78. write(fds[1], buf, str_len);
    79. }
    80. close(clnt_sock);
    81. puts("client disconnected...");
    82. return 0;
    83. }
    84. else{
    85. close(clnt_sock);
    86. }
    87. }
    88. close(serv_sock);
    89. return 0;
    90. }

  • 相关阅读:
    合众汽车选用风河Wind River Linux系统
    CSS的三大特性
    使用公式在Excel中指定列值的变化实现自动间隔着色(不是按照固定的行数)
    AR汽车行业解决方案系列之2-远程汽修
    点云从入门到精通技术详解100篇-基于深度学习的三维植物点云分割网络
    leetcode刷题(122)——62. 不同路径
    细胞膜仿生胶束纳米颗粒/细胞膜和线粒体双靶向紫杉醇纳米胶束的相关研究
    易基因直播预告|细菌微生物基因表达调控表观研究易基因科技
    我的前端开发技巧
    CANoe-以太网软硬件网络自动映射的问题
  • 原文地址:https://blog.csdn.net/weixin_43863869/article/details/132779468