zoukankan      html  css  js  c++  java
  • 和菜鸟一起深入学习国嵌实验之进程间通信

    1、 无名管道

    代码:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <errno.h>
    #include <math.h>
     
    int main(int argc, char *argv[])
    {
       pid_t pid;
       int pipe_fd[2];
       char buf_r[100];
       char *p_wbuf;
       int r_num;
     
       memset(buf_r, 0, sizeof(buf_r));
     
       if(pipe(pipe_fd) < 0)
        {
           printf("pipe create error\n");
           return -1;
        }
     
       //create child process
       if((pid = fork()) == 0)
        {
            printf("\n");
           close(pipe_fd[1]); 
           sleep(2);
           
           if((r_num = read(pipe_fd[0], buf_r, 100)) > 0)
               printf("%d numbers read from the pipe is %s\n", r_num, buf_r);
           
           close(pipe_fd[0]);
           
            exit(0);
           
        }
       else if(pid > 0)
        {
           close(pipe_fd[0]);
           if(write(pipe_fd[1], "Hello", 5) != -1)
               printf("parent write1 Hello\n");
           if(write(pipe_fd[1], "Pipe", 5) != -1)
               printf("parent write2 Pipe\n");
     
           close(pipe_fd[1]);
           waitpid(pid, NULL, 0);
           exit(0);
        }
     
       return 0;
    }


    Makefile:

    CC = gcc
     
    CURTDIR = $(shell pwd)
    TARGET = mypipe
     
    %.o:%.c
           $(CC)-c $(EXTRAFLAGS) $< -o $@
    %.o:%.S
           $(CC)-c $(EXTRAFLAGS) $< -o $@
     
    .PHONY: all clean
     
    $(TARGET): $(TARGET).o
           $(CC)  -o $@ $^
     
    clean:
           rm-rf $(TARGET) $(TARGET).o


    运行结果:

    eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.1$make
    gcc -c mypipe.c -o mypipe.o
    gcc -o mypipe mypipe.o
     
    eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.1$ls
    Makefile mypipe  mypipe.c  mypipe.o
     
    eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.1$./mypipe
    parent write1 Hello
    parent write2 Pipe
     
    10 numbers read from the pipe is HelloPipe
     

    结论:由于fork函数让子进程完整地拷贝了父进程的整个地址空间,所以父子进程都有管道的读端和写端。而我们需要的是一个进程读,一个进程写,所以写的进程最好关闭读端,读的进程关闭写端。

     

    2、 有名管道

    代码1:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <errno.h>
    #include <math.h>
    #define FIFO_SERVER "/tmp/myfifo"
     
    int main(int argc, char *argv[])
    {
       int fd;
       char w_buf[100];
       int nwrite;
     
       if((mkfifo(FIFO_SERVER, O_CREAT | O_EXCL | O_RDWR) < 0)
               && (errno!= EEXIST))
           printf("cannot create fifoserver\n");
     
       fd = open(FIFO_SERVER, O_RDWR | O_NONBLOCK, 0);
       if(fd == -1)
        {
           perror("open");
           exit(1);
        }
     
       if(argc == 1)
        {
           printf("please send something\n");
           exit(-1);
        }
     
       strcpy(w_buf, argv[1]);
       if((nwrite == write(fd, w_buf, 100)) == -1)
        {
           if(errno == EAGAIN)
               printf("The FIFO has not been read yet. please try later\n");
        }
       else
           printf("write %s to the FIFO\n", w_buf);
       
       close(fd);
       
       return 0;
    }


    代码2:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <errno.h>
    #include <math.h>
    #define FIFO_SERVER "/tmp/myfifo"
     
    int main(int argc, char *argv[])
    {
       int fd;
       char buf_r[100];
       int nread;
     
       if((mkfifo(FIFO_SERVER, O_CREAT | O_EXCL | O_RDWR) < 0)
               && (errno!= EEXIST))
           printf("cannot create fifoserver\n");
     
       fd = open(FIFO_SERVER, O_RDWR | O_NONBLOCK, 0);
       if(fd == -1)
        {
           perror("open");
           exit(1);
        }
     
       while(1)
        {
           memset(buf_r, 0, sizeof(buf_r));
           if(nread = read(fd, buf_r, 100) == -1)
           {
               if(errno == EAGAIN)
                    printf("no datayet\n");
           }
           printf("read %s from FIFO\n", buf_r);
           sleep(1);
        }
       
       close(fd);
       pause();
       unlink(FIFO_SERVER);
     
       return 0;
    }


    Makefile:

    CC = gcc
     
    CURTDIR = $(shell pwd)
    TARGET = myfifo_write
    #TARGET = myfifo_read
     
    %.o:%.c
           $(CC)-c $(EXTRAFLAGS) $< -o $@
    %.o:%.S
           $(CC)-c $(EXTRAFLAGS) $< -o $@
     
    .PHONY: all clean
     
    $(TARGET): $(TARGET).o
           $(CC)  -o $@ $^
     
    clean:
           rm-rf $(TARGET) $(TARGET).o
           rm-rf $(TARGETR) $(TARGETR).o
     


    运行结果:

    eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.2$sudo ./myfifo_write hello
    write hello to the FIFO
    eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.2$sudo ./myfifo_write fifo
    write fifo to the FIFO
     
    eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.2$sudo ./myfifo_read
    no data yet
    read from FIFO
    no data yet
    read from FIFO
    no data yet
    read from FIFO
    read hello from FIFO
    no data yet
    read from FIFO
    read fifo from FIFO
    no data yet
    read from FIFO
     

    总结:先创建一个有名管道,打开管道之后向管道中写入由主函数传入的字符串,然后另一个进程循环从管道中读取数据。当没有数据时,是读不到的,当有数据时,就可以读到了。

     

    3、 信号处理

    代码:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <errno.h>
    #include <math.h>
    #include <signal.h>
     
    void my_func(int sign_no)
    {
       if(sign_no == SIGBUS)
        {
           printf("I have get SIGBUS\n");
        }
    }
     
    int main(int argc, char *argv[])
    {
       printf("Waiting for signal SIGBUS\n");
     
       signal(SIGBUS, my_func);
     
        pause();
       return 0;
    }


    Makefile:

    CC = gcc
     
    CURTDIR = $(shell pwd)
    TARGET = mysig
     
    %.o:%.c
           $(CC)-c $(EXTRAFLAGS) $< -o $@
    %.o:%.S
           $(CC)-c $(EXTRAFLAGS) $< -o $@
     
    .PHONY: all clean
     
    $(TARGET): $(TARGET).o
           $(CC)  -o $@ $^
     
    clean:
           rm-rf $(TARGET) $(TARGET).o


    运行结果:

    eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.3$make
    gcc -c mysig.c -o mysig.o
    gcc -o mysig mysig.o
     
    eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.3$ls
    Makefile mysig  mysig.c  mysig.o
     
     
    eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.3$./mysig
    Waiting for signal SIGBUS
     
     
    eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.3$ps -aux | grep mysig
    Warning: bad ps syntax, perhaps a bogus'-'? See http://procps.sf.net/faq.html
    eastmoon 10270  0.0 0.4   9116  3124 pts/2   S+   15:09   0:00 vi mysig.txt
    eastmoon 10295  0.0 0.0   1728   244 pts/3   S+   15:10   0:00 ./mysig
    eastmoon 10300  0.0 0.1   5804   876 pts/4   S+   15:11   0:00 grep --color=auto mysig
    eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.3$kill -BUS 10295
     
     
    eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.3$./mysig
    Waiting for signal SIGBUS
    I have get SIGBUS


    总结:signal系统调用为SIGBUS信号注册了信号处理函数,然后将进程挂起等待SIGBUS信号,当向该进程发送SIGBUS信号才会执行信号处理函数。

     

    4、 共享内存

    代码1:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include <unistd.h>
    #include <errno.h>
    #include <math.h>
    #include <signal.h>
    #include "shm_com.h"
     
    int main(int argc, char *argv[])
    {
       int running = 1;
       void *shared_memory = (void*)0;
       struct shared_use_st *shared_stuff;
       int shmid;
     
       shmid = shmget((key_t)1234, sizeof(struct shared_use_st),
             0666|IPC_CREAT);
      
       if(shmid == -1)
        {
           fprintf(stderr, "shmget failed\n");
           exit(EXIT_FAILURE);
        }
     
       shared_memory = shmat(shmid, (void*)0, 0);
       if(shared_memory == (void*)-1)
        {
           fprintf(stderr, "shmmat failed\n");
           exit(EXIT_FAILURE);
        }
       printf("Memory attached at %x\n", (int)shared_memory);
     
       shared_stuff = (struct shared_use_st *)shared_memory;
     
       shared_stuff->written_by_you = 0;
     
       while(running)
        {
           if(shared_stuff->written_by_you)
           {
               printf("You wrote: %s\n", shared_stuff->some_text);
               sleep(1);
               shared_stuff->written_by_you = 0;
               if(strncmp(shared_stuff->some_text, "end", 3) == 0)
               {
                    running = 0;
               }
           }
        }
     
       if(shmdt(shared_memory) == -1)
        {
           fprintf(stderr, "shmmdt failed\n");
           exit(EXIT_FAILURE);
        }
     
       return 0;
    }
     

    代码2:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include <unistd.h>
    #include <errno.h>
    #include <math.h>
    #include <signal.h>
    #include "shm_com.h"
     
    int main(int argc, char *argv[])
    {
       int running = 1;
       void *shared_memory = (void*)0;
       struct shared_use_st *shared_stuff;
       char buffer[BUFSIZ];
       int shmid;
     
       shmid = shmget((key_t)1234, sizeof(struct shared_use_st),
             0666|IPC_CREAT);
      
       if(shmid == -1)
        {
           fprintf(stderr, "shmget failed\n");
           exit(EXIT_FAILURE);
        }
     
       shared_memory = shmat(shmid, (void*)0, 0);
       if(shared_memory == (void*)-1)
        {
           fprintf(stderr, "shmmat failed\n");
           exit(EXIT_FAILURE);
        }
       printf("Memory attached at %x\n", (int)shared_memory);
     
       shared_stuff = (struct shared_use_st *)shared_memory;
     
       shared_stuff->written_by_you = 0;
     
       while(running)
        {
           while(shared_stuff->written_by_you)
           {
               sleep(1);
               printf("Waiting for client....\n");
           }
          
           printf("Enter some text: ");
           fgets(buffer, BUFSIZ, stdin);
           strncpy(shared_stuff->some_text, buffer, TEXT_SZ);
           shared_stuff->written_by_you = 1;
           if(strncmp(buffer, "end", 3) == 0)
           {
               running = 0;
           }
        }
     
       if(shmdt(shared_memory) == -1)
        {
           fprintf(stderr, "shmmdt failed\n");
           exit(EXIT_FAILURE);
        }
     
       return 0;
    }


    代码3:

    #define TEXT_SZ 2048
     
    struct shared_use_st
    {
       int written_by_you;
       char some_text[TEXT_SZ];
    };


    Makefile:

    CC = gcc
     
    CURTDIR = $(shell pwd)
    #TARGET = myshm1
    TARGET = myshm2
     
    %.o:%.c
           $(CC)-c $(EXTRAFLAGS) $< -o $@
    %.o:%.S
           $(CC)-c $(EXTRAFLAGS) $< -o $@
     
    .PHONY: all clean
     
    $(TARGET): $(TARGET).o
           $(CC)  -o $@ $^
     
    clean:
           rm-rf $(TARGET) $(TARGET).o
     

    运行结果:

    eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.4$make
    gcc -c myshm1.c -o myshm1.o
    gcc -o myshm1 myshm1.o
    eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.4$ls
    Makefile myshm1  myshm1.c  myshm1.o myshm2.c  shm_com.h
     
    eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.4$make
    gcc -c myshm2.c -o myshm2.o
    gcc -o myshm2 myshm2.o
    eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.4$ls
    Makefile myshm1  myshm1.c  myshm1.o myshm2  myshm2.c  myshm2.o shm_com.h
     
    eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.4$./myshm1
    Memory attached at b78db000
     
    eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.4$./myshm2
    Memory attached at b7731000
    Enter some text: my first share memory
    Waiting for client....
    Waiting for client....
    Enter some text: it's so good
    Waiting for client....
    Waiting for client....
    Enter some text: ok, now let's study otherthings.                                            
    Waiting for client....
    Waiting for client....
    Enter some text: end    
     
    eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.4$./myshm1
    Memory attached at b78db000
    You wrote: my first share memory
     
    You wrote: it's so good
     
    You wrote: ok, now let's study otherthings.
     
    You wrote: end


    总结:用于通信的两个进程必须用同一块共享内存进行通信,所以shmget的第一个参数key必须是相同的。

     

    5、 消息队列

    代码1:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <errno.h>
    #include <math.h>
    #include <signal.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
     
    struct my_msg_st
    {
       long int my_msg_type;
       char some_text[BUFSIZ];
    };
     
    int main(int argc, char *argv[])
    {
       int running = 1;
       int msgid;
       struct my_msg_st some_data;
       long int msg_to_receive = 0;
     
       msgid = msgget((key_t)2222, 0666 | IPC_CREAT);
       if(msgid == -1)
        {
           fprintf(stderr, "msgget failed with error: %d\n", errno);
           exit(EXIT_FAILURE);
        }
     
       while(running)
        {
           if(msgrcv(msgid, (void*)&some_data, BUFSIZ, msg_to_receive, 0) ==-1)
           {
               fprintf(stderr, "msgrcv failed with error: %d\n", errno);
               exit(EXIT_FAILURE);
           }
     
           printf("You wrote: %s\n", some_data.some_text);
     
           if(strncmp(some_data.some_text, "end", 3) == 0)
           {
               running = 0;
           }
       }       
       
       if(msgctl(msgid, IPC_RMID, 0) == -1)
        {
           fprintf(stderr, "msgctl failed with error: %d\n", errno);
            exit(EXIT_FAILURE);
        }
       
       return 0;
    }


    代码2:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <errno.h>
    #include <math.h>
    #include <signal.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
     
    struct my_msg_st
    {
       long int my_msg_type;
       char some_text[BUFSIZ];
    };
     
    int main(int argc, char *argv[])
    {
       int running = 1;
       int msgid;
       struct my_msg_st some_data;
       char buffer[BUFSIZ];
     
        msgid= msgget((key_t)2222, 0666 | IPC_CREAT);
       if(msgid == -1)
        {
           fprintf(stderr, "msgget failed with error: %d\n", errno);
           exit(EXIT_FAILURE);
        }
     
       while(running)
        {
           printf("Enter some text:");
           fgets(buffer, BUFSIZ, stdin);
           
           some_data.my_msg_type = 1;
           strcpy(some_data.some_text, buffer);
     
           if(msgsnd(msgid, (void*)&some_data, BUFSIZ, 0) == -1)
           {
               fprintf(stderr, "msgsnd failed with error: %d\n", errno);
               exit(EXIT_FAILURE);
           }
     
           if(strncmp(some_data.some_text, "end", 3) == 0)
           {
               running = 0;
           }
        }
     
       return 0;
    }


    Makefile:

    CC = gcc
     
    CURTDIR = $(shell pwd)
    TARGET = mymsg1
    #TARGET = mymsg2
     
    %.o:%.c
           $(CC)-c $(EXTRAFLAGS) $< -o $@
    %.o:%.S
           $(CC)-c $(EXTRAFLAGS) $< -o $@
     
    .PHONY: all clean
     
    $(TARGET): $(TARGET).o
           $(CC)  -o $@ $^
     
    clean:
           rm-rf $(TARGET) $(TARGET).o
     
     

    运行结果:

    eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.5$make
    gcc -c mymsg1.c -o mymsg1.o
    gcc -o mymsg1 mymsg1.o
     
    eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.5$ls
    Makefile mymsg1  mymsg1.c  mymsg1.o
     
    eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.5$make
    gcc -c mymsg2.c -o mymsg2.o
    gcc -o mymsg2 mymsg2.o
     
    eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.5$ls
    Makefile mymsg1  mymsg1.c  mymsg1.o mymsg2  mymsg2.c  mymsg2.o
     
     
    eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.5$./mymsg2
    Enter some text:hello
    Enter some text:mymsg
    Enter some text:good-buy   
    Enter some text:end
     
     
    eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.5$./mymsg1
    You wrote: hello
     
    You wrote: mymsg
     
    You wrote: good-buy
     
    You wrote: end
     


    总结:在没有运行msg2向消息队列中添加消息的时候,msg1会阻塞在msgrcv函数上,运行msg2后,每添加一条消息,msg1就读取一条,直到添加的消息为”end”,结束。


  • 相关阅读:
    MSSQL—列记录合并
    MSSQL—字符串分离(Split函数)
    如何在ASP.NET Core中自定义Azure Storage File Provider
    从零开始实现ASP.NET Core MVC的插件式开发(六)
    对ASP.NET程序员非常有用的85个工具
    vs-code 配置
    idea-plugin
    VirtualBox中CentOS遇到的问题
    监听器
    线程组复杂场景
  • 原文地址:https://www.cnblogs.com/wuyida/p/6300020.html
Copyright © 2011-2022 走看看