进程间通信

进程间通信

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

二、

1 、管道:pipe()

一切设备皆文件

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

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

管道pipe 要在fork 之前

2 fifo

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

 

/* 信号量:

 

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

 

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

 

  2 semctl:

 

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

 

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

 

     semop(semid, op, num)

 

  4 p 操作能使进程阻塞,不够减的时候阻塞,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);

 

}

 

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

 

    msgctl(msgid, IPC_RMID, NULL);

 

  2 msgrcvmsgsnd 多一个参数

 

*/

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);

    }

}

 

/* 信号量:

 

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

 

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

 

  2 semctl:

 

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

 

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

 

     semop(semid, op, num)

 

  4 p 操作能使进程阻塞,不够减的时候阻塞,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);

}

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

 

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

 

  2 shmctl:

 

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

 

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

 

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

 

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

 

  4 shmdt: 删除映射

 

  建立,删除映射都会影响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)

 

  4 munmap() 解除映射。

 

  */

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);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值