进程间通信

来源:互联网 发布:欧路莎卫浴 知乎 编辑:程序博客网 时间:2024/05/20 04:49

进程间通信

一、主要函数:pipe();msgsnd();msgrcv();

二、

1、管道:pipe()

一切设备皆文件

管道属于内核,是内核的一片内存,fork不会有这样的内存

管道没有数据时会阻塞。一旦数据被从管道里读出来,那么管道里就没有这个数据了。管道的数据,读完了就没有了,不像文件。

管道pipe要在fork之前

2fifo

1)mkfifo创建一个fifo文件"test"

 

  fifo也是有大小限制的,最大为65536,如果没有数据也会阻塞

 

  注:尽量少用fifo

 

2)/*如果写端已关闭,那么读端不再阻塞,会跟着返回*/

/*如果写一个读端已经关闭的管道,则直接出错?会产生一个SIGPIPE信号,这个信号默认在内核直接杀死进程。*/

 

3、消息队列:

1)ftok生成一个key:

 

2)msgget取得或创建一个ipc对象(根据key):

 

3)如果有必要则初始化ipc

 

4)操作ipc: msgsnd,msgrcv:

 

注意:类型(mtype)要一样才能接收

 

struct msqid_ds

qnum

IPC_RMID :可用于消除msqrcv阻塞

IPC_STAT :可获得消息队列的信息

 

msgsnd();msgrcv();

client,server

 

4、信号量:semget,semctl,semop

 

/*信号量:

 

  1semget:若是父子进程之间通信,可用IPC_PRIVATE作为key

 

     semid = semget(IPC_PRIVATE, num, IPC_CREAT | 0600);

 

  2semctl:

 

     semctl(semid, i, SETVAL, semval);//i表示第几个信号量

 

  3semop:  p操作(-1),v操作(+1);

 

     semop(semid, op, num)

 

  4p操作能使进程阻塞,不够减的时候阻塞,v操作不会阻塞,而且一般不会出错

 

  5、如迅雷下载只能有8个任务同时进行,这就是信号量。。。。。。

 

*/

信号量常用的三种算法:

信号量(1):互斥

信号量(2):一个信号量,多个子进程

信号量(3):栅栏同步,多个信号量

一个进程里的全局变量,另一个进程是看不到的。

进程之间要互斥的话,则要用同一信号量;信号量一般用于多线程。

 

5、共享内存:shmget,shmctl,shmat,shmdt

共享内存,很适合于进程间通信,不同进程之间在一定条件下是可以看得到的

 

mmap函数

 

三、例程

1

/*pipe.c*/

 

#include <stdio.h>

 

#include <stdlib.h>

 

#include <unistd.h>

 

 

int main(void)

 

{

 

    int fd[2];

 

    int ret = pipe(fd);

 

    if (ret == -1) {

 

        perror("pipe");

 

        exit(1);

 

    }


 

    pid_t pid = fork();

 

    if (pid == -1) {

 

        perror("fork");

 

        close(fd[0]);

 

        close(fd[1]);

 

        exit(0);

 

    }

 

    if (pid == 0) {

 

        char buf[32];

 

        //close(fd[1]);

 

        printf("read begin!/n");

 

        ret = read(fd[0], buf, 32);

 

        buf[ret-1] = '/0';

 

        printf("%s/n", buf);

 

        close(fd[0]);

 

        exit(0);

 

    }

 

    if (pid > 0) {

 

        //close(fd[0]);

 

        sleep(3);

 

        write(fd[1], "Hello world!", 12);

 

        wait(NULL);

 

        exit(0);

 

    }

 

}

 

/*确保管道一端写,一端读*/

2

/*endpipe.c*/

 

#include <stdio.h>

 

#include <stdlib.h>

 

#include <unistd.h>

 

int main(void)

 

{

 

    int fd[2], ret;

 

    char buf[32];

 

    ret = pipe(fd);

 

    if (ret == -1) {

 

        perror("pipe");

 

        exit(1);

 

    }

 

    pid_t pid = fork();

 

    if (pid > 0) {

 

        close(fd[1]);

 

        printf("Begin read!/n");

 

        ret = read(fd[0], buf, 32);

 

        if (ret == -1) {

 

            perror("read");

 

            exit(1);

 

        }

 

        if (ret == 0) {

 

            printf("The pipe is empty!/n");

 

        }

 

        close(fd[0]);

 

        exit(0);

 

    }

 

    if (pid == 0) {

 

        sleep(10);

 

        exit(0);

 

    }

 

}

 

/*如果写端已关闭,那么读端不再阻塞,会跟着返回*/

3

/*brokenpipe.c*/

 

#include <stdio.h>

 

#include <stdlib.h>

 

#include <unistd.h>

 

#include <signal.h>

 

void pipe_handler(int s)

 

{

 

 

}

 

int main(void)

 

{

 

    int fd[2], ret;

 

    char buf[32];

 

    ret = pipe(fd);

 

    if (ret == -1) {

 

        perror("pipe");

 

        exit(1);

 

    }

 

    signal(SIGPIPE, pipe_handler);

 

    pid_t pid = fork();

 

    if (pid > 0) {

 

        close(fd[0]);

 

        wait(NULL);

 

        printf("Begin write!/n");

 

        ret = write(fd[1], buf, 32);

 

        if (ret == -1) {

 

            perror("write");

 

            exit(1);

 

        }

 

        if (ret == 0) {

 

            printf("The pipe can not write!/n");

 

        }

 

        printf("father exit!/n");

 

        close(fd[1]);

 

        exit(0);

 

    }

 

    if (pid == 0) {

 

        sleep(5);

 

        exit(0);

 

    }

 

}

 

/*如果写一个读端已经关闭的管道,则直接出错?会产生一个SIGPIPE信号,这个信号默认在内核直接杀死进程。*/

4

 

5

/*repipe.c*/

 

#include <stdio.h>

 

#include <stdlib.h>

 

#include <unistd.h>

 

int main(void)

 

{

 

    int ret, fd[2];

 

 

 

    ret = pipe(fd);

 

    if (ret == -1) {

 

        perror("pipe");

 

        exit(1);

 

    }

 

    pid_t pid = fork();

 

    if (pid == -1) {

 

        perror("fork");

 

        close(fd[0]);

 

        close(fd[1]);

 

        exit(1);

 

    }

 

    if (pid == 0) {

 

        close(fd[1]);

 

        dup2(fd[0], 0);

 

        execlp("grep", "grep", "d", NULL);

 

        exit(0);

 

    }

 

    if (pid > 0) {

 

        close(fd[0]);

 

        dup2(fd[1], 1);

 

        execlp("ls", "ls", "-al", "./", NULL);

 

        exit(0);

 

    }

 

}

 

/*相当于shell命令行中的 ls -al ./ | grep d */

6

/*pipeseize.c*/

 

#include <stdio.h>

 

#include <stdlib.h>

 

#include <unistd.h>

 

#include <signal.h>

 

#include <fcntl.h>

 

static int cnt = 0;

 

void alarm_handler(int s)

 

{

 

    printf("Pipe max size is %d/n", cnt);

 

}

 

int main(void)

 

{

 

    int fd[2];

 

    int ret = pipe(fd);

 

    if (ret == -1) {

 

        perror("pipe");

 

        exit(1);

 

    }

 

   signal(SIGALRM, alarm_handler);

 

    ret = fcntl(fd[1], F_GETFL);

 

    fcntl(fd[1], F_SETFL, ret | O_NONBLOCK);

 

    while (1) {

 

        ret = write(fd[1], "x", 1);

 

        if (ret == -1) {

 

            printf("Pipe max size is %d/n",

 

                cnt);

 

            break;

 

        }

 

        cnt += ret;

 

        //alarm(1);    

 

    }

 

}

 

/*测试管道的大小*/

7

/*fifo_write_end.c*//*fifo的写端*/

 

#include <stdio.h>

 

#include <stdlib.h>

 

#include <fcntl.h>

 

#include <unistd.h>


 

int main(void)

 

{

 

    int fd;


 

    printf("write end:before open!/n");

 

    fd = open("test", O_WRONLY);

 

    if (fd == -1) {

 

        perror("open");

 

        exit(1);

 

    }

 

    printf("write end:Open success!/n");

 

    sleep(5);

 

    write(fd, "Hello world!", 12);

 

    close(fd);

 

    exit(0);

 

}

 

/*事先用mkfifo创建一个fifo文件"test"

 

  fifo也是有大小限制的,最大为65536,如果没有数据也会阻塞

 

  注:尽量少用fifo

 

*/

8

/*fifo_read_end.c*//*fifo的读端*/

 

#include <stdio.h>

 

#include <stdlib.h>

 

#include <fcntl.h>

 

#include <unistd.h>

 

int main(void)

 

{

 

    int fd, ret;

 

    char buf[32];

 

    printf("before open!/n");

 

    fd = open("test", O_RDONLY);

 

    if (fd == -1) {

 

        perror("open");

 

        exit(1);

 

    }

 

    printf("Open success!/n");

 

    ret = read(fd, buf, 32);

 

    buf[ret-1] = '/0';

 

    printf("%s/n", buf);

 

    close(fd);

 

    exit(0);

 

}

9

/*msgsnd.c*//*消息队列*/

 

#include <sys/types.h>

 

#include <sys/ipc.h>

 

#include <sys/msg.h>

 

#include <stdio.h>

 

#include <stdlib.h>

 

#include <string.h>

 

#define PATHNAME "/etc/passwd"

 

#define PROJID 123

 

struct stu {

 

    char name[20];

 

    float avg;

 

};

 

struct msgbuf {

 

    long mtype;

 

    struct stu student;

 

};

 

int main(void)

 

{

 

    key_t key = ftok(PATHNAME, PROJID);

 

    if (key == -1) {

 

        perror("ftok");

 

        exit(1);

 

    }

 

    int msgid = msgget(key, IPC_CREAT | 0600);

 

    if (msgid == -1) {

 

        perror("msgget");

 

        exit(1);

 

    }      

 

    struct msgbuf buf;//封装要发送的数据

 

    buf.mtype = 8;

 

    strcpy(buf.student.name, "Allan");

 

    buf.student.avg = 99.999;

 

    int ret = msgsnd(msgid, &buf,

 

        sizeof(buf) - sizeof(long), 0);

 

    if (ret == -1) {

 

        perror("msgsnd");

 

        exit(1);

 

    }

 

    exit(0);

 

}

 

/*消息队列:

 

1、用ftok生成一个key:

 

2、用msgget取得或创建一个ipc对象(根据key):

 

3、如果有必要则初始化ipc

 

4、操作ipc: msgsnd,msgrcv:

 

*/

10

/*msgrcv.c*//*消息队列*/

 

#include <sys/types.h>

 

#include <sys/ipc.h>

 

#include <sys/msg.h>

 

#include <stdio.h>

 

#include <stdlib.h>

 

#include <string.h>

 

#define PATHNAME "/etc/passwd"

 

#define PROJID 123

 

struct stu {

 

    char name[20];

 

    float avg;

 

};

 

struct msgbuf {

 

    long mtype;

 

    struct stu student;

 

};

 

int main(void)

 

{

 

    key_t key = ftok(PATHNAME, PROJID);

 

    if (key == -1) {

 

        perror("ftok");

 

        exit(1);

 

    }

 

#if 0

 

    int msgid = msgget(key, IPC_CREAT | 0600);

 

    if (msgid == -1) {

 

        perror("msgget");

 

        exit(1);

 

    }      

 

#endif

 

    int msgid = 196608;

 

    struct msqid_ds buffer;

 

    msgctl(msgid, IPC_STAT, &buffer);

 

    if (buffer.msg_qnum == 0) {

 

        msgctl(msgid, IPC_RMID, NULL); 

 

        exit(0);

 

    }

 

    struct msgbuf buf;


 

    int ret = msgrcv(msgid, &buf,

 

        sizeof(buf) - sizeof(long), 8, 0);

 

    if (ret == -1) {

 

        perror("msgsnd");

 

        exit(1);

 

    }


 

    printf("name=%s/n", buf.student.name);

 

    printf("score=%f/n", buf.student.avg);

 

    exit(0);

 

}

 

/*1if (buffer.msg_qnum == 0)

 

    msgctl(msgid, IPC_RMID, NULL);

 

  2msgrcvmsgsnd多一个参数

 

*/

11

/*2010-09-24*/

/*信号量(1):互斥*/

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

int sem_init(int num,int semval)

{

    int semid=semget(IPC_PRIVATE,num,IPC_CREAT | 0600);

    if(semid==-1)

    {

        perror("semge");

        return -1;

    }

    int i,ret;

    for(i=0;i<num;i++)

    {

        ret=semctl(semid,i,SETVAL,semval);//i为下标!

        if(ret==-1)

        {

            perror("semctl");

            return -1;

        }

    }

    return semid;

}

int p(int semid,int num)

{

    struct sembuf op[num];

    int i;

    for(i=0;i<num;i++)

    {

        op[i].sem_num=i;//哪个信号量

        op[i].sem_op=-1;//执行什么样的操作,-1表示减

        op[i].sem_flg=0;//一般写0OK

    }

    int ret;

    while(ret=semop(semid,op,num));//操作成功返回0,则跳出while,否则就停在这。也就是semop出错返回-1时不再往下走。

    return ret;

}

void v(int semid,int num)

{

    struct sembuf op[num];

    int i;

    for(i=0;i<num;i++)

    {

        op[i].sem_num=i;//哪个信号量

        op[i].sem_op=1;//执行什么样的操作,-1表示减

        op[i].sem_flg=0;//一般写0OK

    }

    semop(semid,op,num);

}

int main(void)

{

    int semid=sem_init(1,1);

    if(semid==-1)

        exit(1);

    pid_t pid=fork();

    if(pid==-1)

    {

        perror("fork");

        exit(1);

    }

    if(pid==0)

    {

        p(semid,1);

        printf("I'm child!/n");

        sleep(20);

        printf("20 seconds passed!/n");

        v(semid,1);

        exit(0);

    }

    if(pid>0)

    {

        p(semid,1);

        printf("I'm father!/n");

        sleep(5);

        v(semid,1);

        exit(0);

    }

}

 

/*信号量:

 

  1semget:若是父子进程之间通信,可用IPC_PRIVATE作为key

 

     semid = semget(IPC_PRIVATE, num, IPC_CREAT | 0600);

 

  2semctl:

 

     semctl(semid, i, SETVAL, semval);//i表示第几个信号量

 

  3semop:  p操作(-1),v操作(+1);

 

     semop(semid, op, num)

 

  4p操作能使进程阻塞,不够减的时候阻塞,v操作不会阻塞,而且一般不会出错

 

  5、如迅雷下载只能有8个任务同时进行,这就是信号量。。。。。。

 

*/

12

/*2010-09-24*/

/*信号量(2):一个信号量,限制同时运行的子进程个数*/

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

#include <signal.h>

#define BASE 30000

#define PROCESSNUM 5 //允许5个同时进行的子进程

int sem_init(int semval)

{

    int semid=semget(IPC_PRIVATE,1,IPC_CREAT | 0600);//只有一个信号量

    if(semid==-1)

    {

        perror("semget");

        return semid;

    }

    int ret=semctl(semid,0,SETVAL,semval);//下标是从0开始的

    if(ret==-1)

    {

        perror("semctl");

        return ret;

    }

    return semid;

}

void p(int semid)

{

    struct sembuf op;

    op.sem_num=0;

    op.sem_op=-1;//-1表示p操作一次,semval1

    op.sem_flg=0;

    semop(semid,&op,1);

}

void v(int semid)

{

    struct sembuf op;

    op.sem_num=0;

    op.sem_op=1;//1表示v操作一次,semval1

    op.sem_flg=0;

    semop(semid,&op,1);

}

void destroyzombie()

{

    struct sigaction act;

    act.sa_handler=SIG_IGN;//不作处理

    sigemptyset(&act.sa_mask);

    act.sa_flags=SA_NOCLDWAIT;

    sigaction(SIGCHLD,&act,NULL);

}

void doprime(int prime)

{

    int i;

    int flag=0;

 

    for(i=2;i<prime;i++)//2 开始

    {

        if(prime%i==0)

        {

            flag=1;

            break;

        }

    }

    if(flag==0)

        printf("%d is a prime!/n",prime);

    else

        printf("%d is not a prime!/n",prime);

}

int main(void)

{

    int semid;

    int i;

 

    semid=sem_init(PROCESSNUM);//PROCESSNUM为信号量的值

    destroyzombie();

    for(i=BASE;i<BASE+100;i++)

    {

        p(semid);//当减不动的时候是否会产生阻塞

        pid_t pid=fork();

        if(pid==-1)

        {

            perror("fork");

            exit(1);

        }

        if(pid==0)

        {

            doprime(i);

            sleep(2);

            v(semid);

            exit(0);

        }

    }

}

 

13

/*栅栏同步,5个信号量,每个信号量的值为1*/

 

/*2010-09-24*/

/*信号量(3):栅栏同步*/

/*让五个人同时开始跑,等所有人都跑完一圈以后再从重新让它们处于同一起跑线上*/

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

#define PRONUM 5

#define PATHNAME "/home/luo/advancedC/tongxin/test"

#define KEY_ID 123

 

int sem_init(int num,int semval)

{

    key_t key=ftok(PATHNAME,KEY_ID);//ftok取得key

    if(key==-1)

    {

        perror("ftok");

        return -1;

    }

    int semid=semget(key,num,IPC_CREAT | 0600);

    if(semid==-1)

    {

        perror("semget");

        return semid;

    }

    int i,ret;

    for(i=0;i<num;i++)

    {

         ret=semctl(semid,i,SETVAL,semval);

         if(ret==-1)

         {

             perror("semctl");

             return -1;

         }

    }

    return semid;

}

int  p(int semid,int num)//num表示第几个信号量

{

    struct sembuf op;

    op.sem_num=num;

    op.sem_op=-1;

    op.sem_flg=0;

    int ret;

 

    while(ret=semop(semid,&op,1));

    return ret;

}

void  v(int semid,int num)

{

    struct sembuf op[num];

    int i;

 

    for(i=0;i<num;i++)

    {

        op[i].sem_num=i;

        op[i].sem_op=1;

        op[i].sem_flg=0;

    }

    semop(semid,op,num);//刚才始写成了semop(semid,op,num);

}

int main(void)

{

    int semid=sem_init(PRONUM,1);//5个信号量,每个信号量的值为1

    int i;

 

    for(i=0;i<PRONUM;i++)

    {

        pid_t pid=fork();

        if(pid==-1)

        {

            perror("fork");

            exit(1);

        }

        if(pid==0)

        {

           while(1)

           {

                p(semid,i);

                srand(getpid());//播种

                printf("pid=%d begin running!/n",getpid());

                sleep(rand()%PRONUM + 3);//产生随机数

                printf("pid=%d run over!/n",getpid());

           }

        }

    }

    while(1)

    {

        for(i=0;i<PRONUM;i++)

        {

            while(semctl(semid,i,GETNCNT)==0);//等所有的都跑完一圈

        }

        v(semid,PRONUM);//从新让它们处于同一起跑线上       

    }

}

 

14

/*shared.c*//*共享内存*/

 

/*2010-09-24*/

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <sys/types.h>

#include <sys/shm.h>

 

void destroy_shm(int shmid)

{

   struct shmid_ds buf;

   shmctl(shmid,IPC_STAT,&buf);//读出信息放于buf

   if(buf.shm_nattch==0)

   {

        shmctl(shmid,IPC_RMID,NULL);

   }

}

int main(void)

{

    int shmid=shmget(IPC_PRIVATE,32,IPC_CREAT | 0600);

    if(shmid==-1)

    {

        perror("shmget");

        exit(1);

    }

    pid_t pid=fork();

    if(pid==-1)

    {

        perror("fork");

        exit(1);

    }

    if(pid==0)

    {

        char* ptr=(char*)shmat(shmid,NULL,0);//映射到共享内存,以操作它

        strncpy(ptr,"hello world!",12);

        shmdt(ptr);

        exit(0);

    }

    wait(NULL);

    sleep(1);

    char* ptr=(char*)shmat(shmid,NULL,0);

    printf("%s/n",ptr);

    shmdt(ptr);

    destroy_shm(shmid);

    exit(0);

}

/*共享内存,很适合于进程间通信

 

  1shmget:获得一个共享存储标识符shmid

 

  2shmctl:

 

  IPC_STAT,取此段的shmid_ds结构,并将它存放在由buf指定的结构中

 

  IPC_RMID,从系统中删除该共享存储段

 

  3shmat:建立映射到所申请的地址空间

 

  一般用法:shmat(shmid, NULL, 0)

 

  4shmdt:删除映射

 

  建立,删除映射都会影响shmid_ds结构中的shm_nattch

 

*/

15

/*mmap.c*/

 

#include <sys/mman.h>

 

#include <stdio.h>

 

#include <stdlib.h>

 

#include <fcntl.h>

 

#include <unistd.h>

 

#include <sys/types.h>

 

#include <sys/stat.h>


 

int main(void)

 

{

 

    int fd, ret, fsize;

 

    char *ptr; 

 

    struct stat buf;

 

    fd = open("/etc/passwd", O_RDONLY);

 

    if (fd == -1) {

 

        perror("open");

 

        exit(1);

 

    }

 

 

    fstat(fd, &buf);

 

    fsize = buf.st_size;   

 

 

    ptr = mmap(NULL, fsize+1, PROT_READ | PROT_WRITE,

 

        MAP_PRIVATE, fd, 0);

 

    if (((void *)(-1)) == ptr) {

 

        perror("mmap");

 

        close(fd);

 

        exit(1);

 

    }  

 

 

    ptr[fsize] = '/0';

 

    printf("%s", ptr);

 

    munmap(ptr, fsize);

 

    close(fd);

 

    exit(0);

 

}

 

/*mmap:

 

  1、若以AP_PRIVATE映射,则不会修改原始文件,

 

  私有映射,写时复制,对副本的操作是可读可写的

 

  2、若以MAP_SHARED映射,用munmap解除映射,解除映射,可以将内存中的内容写到磁盘里

 

  3、可用fstat先获得文件的长度再映射

 

  父子进程可mmap共享内存,无关进程不可以??

 

  以匿名方式申请内存,这个内存会自动被清零的:

 

  mmap(NULL,32,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0)

 

  4munmap()解除映射。

 

  */

16

/*anonmous.c*/

 

#include <sys/mman.h>

 

#include <stdio.h>

 

#include <stdlib.h>

 

#include <fcntl.h>

 

#include <unistd.h>

 

#include <sys/types.h>

 

#include <sys/stat.h>

 

#include <string.h>

 

int main(void)

 

{

 

    char *ptr; 

 

    pid_t pid;

 

   

 

    ptr = (char *)mmap(NULL, 32, PROT_READ |

 

        PROT_WRITE, MAP_PRIVATE |

 

            MAP_ANONYMOUS, -1, 0);

 

    if (((void *)(-1)) == ptr) {

 

        perror("mmap");

 

        exit(1);

 

    }  

 

 

    pid = fork();

 

    if (pid == -1) {

 

        perror("fork");

 

        munmap(ptr, 32);

 

        exit(1);

 

    }

 

    if (pid == 0) {

 

        strcpy(ptr, "Hello world!");

 

        munmap(ptr, 32);

 

        exit(0);

 

    }

 

    wait(NULL);

 

    printf("%s/n", ptr);

 

    munmap(ptr, 32);

 

    exit(0);

 

}

 

/* MAP_PRIVATE | MAP_ANONYMOUS以这种方式申请的内存有什么??

 

   父子进程都munmap()难道不会影响吗?

 

  */

16、

/*test_share_shm_write_int_type.c*/
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define TOKEN 'r'

void destroy_shm(int shmid)
{
    struct shmid_ds buf;
    shmctl(shmid, IPC_STAT, &buf);
    if (buf.shm_nattch == 0)
        shmctl(shmid, IPC_RMID, NULL);
}

int main(void)
{
    int shmid = shmget(IPC_PRIVATE, 32, IPC_CREAT | 0600);
    if (shmid == -1) {
        perror("shmget");
        exit(1);
    }

    pid_t pid = fork();
    if (pid == -1) {
        destroy_shm(shmid);
        perror("fork");
        exit(1);
    }

    if (pid == 0) {
        int n=5;
        int *ptr = (int *)shmat(shmid, NULL, 0);
        *ptr=n;
        shmdt(ptr);
        int *rptr=(int *)shmat(shmid,NULL,0);
        printf("child read n=%d/n",*rptr);
        shmdt(rptr);
        exit(0);
    }
    sleep(2);
    int rea;
    int *ptr = (int *)shmat(shmid, NULL, 0);
    printf("father read n=%d/n",*ptr);
    shmdt(ptr);
    destroy_shm(shmid);
    exit(0);
}
17、

/*pipe每得到的是未被使用的描述符*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{
    int i;
    for(i=0;i<3;i++)
    {
        int fd[2];

        int ret = pipe(fd);
        printf("fd[0]=%d/n",fd[0]);
        printf("fd[1]=%d/n",fd[1]);
        if (ret == -1) {
            perror("pipe");
            exit(1);
        }

        pid_t pid = fork();
        if (pid == -1) {
            perror("fork");
            close(fd[0]);
            close(fd[1]);
            exit(0);
        }

        if (pid == 0) {
            char buf[32];
            //close(fd[1]);
            printf("read begin!/n");
            ret = read(fd[0], buf, 32);
            buf[ret-1] = '/0';
            printf("%s/n", buf);
            close(fd[0]);
            exit(0);
        }

        if (pid > 0) {
            //close(fd[0]);
            sleep(3);
            write(fd[1], "Hello world!", 12);
            wait(NULL);
        }
    }
}

原创粉丝点击