进程通信

来源:互联网 发布:旅游线路图软件 编辑:程序博客网 时间:2024/05/22 23:58
一、进程通信----共享内存
父子进程之间为例:
流程:
1. 创建共享内存
2. 创建子进程
3. 父进程中  映射内存  向内存写数据strncpy  wait同步子进程
4. 子进程中  映射内存  等待父进程写入sleep  操作内存(可读)
 

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define PERM S_IRUSR|S_IWUSR

int main(int argc, char **argv)
{
    int shmid;
    char *f_addr, *c_addr;

    if(argc != 2)
    {
        printf("Usage: ./shm ni hao \n");
        exit(1);
    }
    if((shmid = shmget(IPC_PRIVATE, 1024, PERM)) < 0) // (()())()

    {
        printf("shmget error:%s\n", strerror(errno));
        exit(1);
    }
    printf("shmget ok!\n");
/*    if( fork() < 0)
    {
        printf("fork error:%s\n", strerror(errno));
        exit(1);
    }*/

    if(fork())
    {
        printf("father process...\n");
        f_addr = shmat(shmid, 0, 0);
        memset(f_addr, '\0', 1024);
        strncpy(f_addr, argv[1],1024);
        printf("father exit!\n");
        wait(NULL);
//        sleep(3);


    }
    else
    {
        sleep(1);
        printf("child process...\n");
        c_addr = shmat(shmid, 0, 0);
        printf("client get:%s\n", c_addr);
    }
}


易错点:

1.int main(int argc, char **argv)

    主函数**argv

2.if((shmid = shmget(IPC_PRIVATE, 1024, PERM)) < 0) // (()())()

先将赋值括起来,然后与0比较, 注意内存属性的描述

3. memset(f_addr, '\0', 1024);

    映射之后,写之前要初始化内存。

4.wait(NULL)

二、进程通信----fifo

   pipe只能用父子经常之间的通信,而fifo适合任何进程之间。
流程:
1.创建fifo,以非阻塞方式打开。
说明:A:在阻塞方式下打开,(没有指定O_NONBLOCK)
(1)当以只读open是,进程阻塞,直到有进程为写而打开;
(2)当以只写open打开时,进程阻塞,直到有进程为读而打开。
   B: 若指定O_NONBLOCK 方式打开
(1)若只读open 将立即返回,若只写open将出错!  所以先创建读进程,后创建写进程。
(即:在创建fifo进程,执行读,其他进程直接打开fifo后,执行写)
2.读操作
3.删除fifo文件
 
例: 在当前文件下创建fifo文件 
fifo_read.c

#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FIFO_SERVER "/tmp/myfifo"

main(void)
{
    int fd;
    int read_size;
    char buf[20];
    if((mkfifo("./myfifo", O_CREAT|O_EXCL) < 0) && (errno != EEXIST)) // !!

    {
        printf("fifo creat error\n");
        exit(1);
    }
    printf("open and reading...\n");
    if((fd = open("./myfifo", O_RDONLY|O_NONBLOCK,0)) < 0) //creat and open in O_NONBLOCK

    {
        printf("open fifo:%s\n", strerror(errno));
        exit(1);
    }
    printf("opened, reading ..\n");
    while(1)
    {
        memset(buf, 0, sizeof(buf));  // 数组要初始化
        if((read_size = read(fd, buf, sizeof(buf))) < 0) //use right number of () 此处一定注意!容易出错!适当的加括号

        {    
            printf("read error:%s\n", strerror(errno));
            exit(1);
        }
        printf("read %s from fifo:%d\n", buf,read_size); // add '\n' in printf, or error 

        sleep(1);        //sleep, execute slowly!

    }
    pause();
    unlink("./myfifo");
}

程序两个容易犯错的地方:

1.  if((read_size = read(fd, buf, sizeof(buf))) < 0) //use right number of () 

此处一定注意!容易出错!适当的加括号


2.printf("read %s from fifo:%d\n", buf,read_size); // add '\n' in printf, or error 

此处注意‘\n’别丢了

fifo_write.c


 

#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FIFO_SERVER "/tmp/myfifo"

int main(int argc, char *argv[])
{
    int fd;
    char w_buf[20];
    int write_size;
    if((fd=open("./myfifo",O_WRONLY | O_NONBLOCK, 0)) < 0)
    {
        printf("open error:%s\n", strerror(errno));
        exit(1);
    }
    printf("open ok\n");
    strcpy(w_buf, argv[1]);
    if((write_size = write(fd, w_buf, sizeof(w_buf))) < 0)
    {
        printf("write error:%s\n", strerror(errno));
        exit(1);
    }
    printf("write %s to fifo\n", w_buf);
    close(fd);
    return 0;
}


三、进程间通信----pipe方式

流程:1.fork创建子进程
     2.pipe创建管道
     3.子进程:关闭写, sleep(2)后,开始read  ,关闭读。
     4.父进程:关闭读,开始write, waitpid,关闭写。
 

#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>

main(void)
{
    int fd[2];
    pid_t child;
    char s[] = "pipe is good!";
    char buf[20];
    if (pipe(fd) < 0)
    {
        printf("create pipe error:%s\n",strerror(errno));
        exit(1);
    }
    if((child = fork()) < 0)
    {
        printf("fork error:%s\n",strerror(errno));
        exit(1);
    }
    if(== child)
    {
        close(fd[1]);         //close another one

        sleep(2);        // must have this    

        printf("child read...\n");
        if(read(fd[0],buf,sizeof(s)) < 0)
        {
            printf("read error:%s\n", strerror(errno));
            exit(1);
        }
        printf("\nread:%s\n", buf);
        close(fd[0]);         //remember to close

//        exit(0);         // no needed 

    }
    else 
    {
        close(fd[0]);
        printf("father process:write...\n");
        if(write(fd[1],s,sizeof(s)) < 0)
        {
            printf("write error:%s\n", strerror(errno));
            exit(1);
        }
        printf("write ok!\n");
        close(fd[1]);        
        waitpid(child, NULL, 0); // must have! compare difference form without

//        exit(0);         // why need this?

    }
}



0 0