进程间通信

来源:互联网 发布:win10 装linux 编辑:程序博客网 时间:2024/06/05 07:38

1、管道方式
1)无名管道:(只能在有亲缘关系的进程间进行通信)

#include<stdio.h>#include<unistd.h>int main(){    int fd[2];    if(pipe(fd)<0){        printf("创建管道失败\n");        return -1;    }    // fd[0] 用于输入    // fd[1] 用于输出    int pid = fork();  // 创建一个子进程    if(pid<0){        printf("创建子进程失败\n");        return -1;    } else if(pid==0){ // 子进程中        write(fd[1], "hello", sizeof("hello"));    } else {           // 父进程中        char msg[8];        read(fd[0], msg, sizeof(msg)-1);        printf("父进程收到消息:%s\n", msg);    }    return 0;}

2)有名管道(如果知道管道名称,可以支持在不同进程中的通信)
创建、写

#include<stdio.h>#include<sys/stat.h>#include<fcntl.h>#include<unistd.h>int main(){    const char *fifo_name = "./hchlqlz";    if(access(fifo_name, F_OK)==-1){  // 判断该管道是否存在        // access函数用于判断当前用户对文件的权限,功能取决于第二个参数        // R_OK, W_OK, X_OK ,是否可读, 可写, 可执行        // F_OK,文件是否存在        if(mkfifo(fifo_name, 0666)==-1){            printf("创建管道失败\n");            return -1;        }    }    int fid = open(fifo_name, O_WRONLY);  // 以只写的方式打开文件    write(fid, "hello", sizeof("hello"));    close(fid);    return 0;}

#include<stdio.h>#include<fcntl.h>#include<unistd.h>int main(){    const char *fifo_name = "./hchlqlz";    int fid = open(fifo_name, O_RDONLY);    char msg[8];    read(fid, msg, sizeof(msg)-1);    close(fid);    printf("%s\n", msg);    return 0;}

注:打开管道时必须同时有读数据进程和写数据进程,缺了某一个,就会阻塞。
2、信号(signal)

#include<stdio.h>#include<unistd.h>#include<signal.h>bool ing = true;void stop(int sig){   // sig:收到的信号    ing = false;}int main(){    signal(2, stop);  // 将信号2与stop函数绑定,如果接收到信号2,则调用stop函数    while(ing){        printf("!");        fflush(NULL); // 刷新缓冲区        sleep(1);     // 休眠1s    }    printf("结束运行\n");    return 0;}

3、消息队列

主要函数:

1)int msgget(key_t, key, int msgflg)
key:消息队列的key
msgflg:权限,可以异或IPC_CREAT、IPC_EXCL(如果不存在该消息队列,返回-1)

2)int msgsnd(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg)
msgid:消息队列id
msg_ptr:指向一个消息的指针,消息结构需要以一个long 作为开始,可以附加其他的信息
msg_sz:消息大小
msgflg:当队列满时进行的操作,0为阻塞,IPC_NOWAIT返回-1

3)int msgrcv(int msgid, void *msg_ptr, size_t msg_st, long int msgtype, int msgflg)
msgtype:指定获取的消息,0:获取队列第一条消息,>0:获取指定类型的第一条消息,<0:获取类型<=msgtype绝对值的第一条消息

4)int msgctl(int msgid, int command, struct msgid_ds *buf)
command:执行的操作,IPC_RMID删除消息队列,IPC_STAT,设置buf,IPC_SET,用buf 设置消息队列的关联值

#include<stdio.h>#include<string.h>#include<sys/msg.h>struct MSG{    long type;    char msg[128];};int main(){    int qid = msgget(1, 0666 | IPC_CREAT);    if(qid==-1){        printf("获取消息队列失败\n");        return -1;    }    MSG s1;    s1.type = 1;    strcpy(s1.msg, "hello1");    msgsnd(qid, &s1, sizeof(s1), 0);    MSG s2;    s2.type = 3;    strcpy(s2.msg, "hello3");    msgsnd(qid, &s2, sizeof(s2), 0);    MSG s3;    msgrcv(qid, &s3, sizeof(s3), 3, 0);    printf("从消息队列中取到的消息是:%s\n", s3.msg);    msgctl(qid, IPC_RMID, 0);    return 0;}

4、共享内存
1)int shmget(key_t key, size_t size, int shmflg)
比消息队列的msgget多了一个size表示共享内存的大小。

2)void *shmat(int shm_id, const void *shm_addr, int shmflg)
刚获取到的共享内存,不能立即投入使用,需要用shmat函数来启动对该共享内存的访问,把共享内存连接到当前进程的地址空间上。
id:标识
addr:连接到当前进程的地址位置,为NULL时由系统进行选择

3)int shmdt(const void *shmaddr)
分离共享内存。

4)int shmctl(int shm_id, int command, struct shmid_ds *buf)
对共享内存进行操控。和消息队列类似

创建并写

#include<stdio.h>#include<string.h>#include<sys/shm.h>struct Student{    char name[16];    char note[128];};int main(){    int sid = shmget(520, sizeof(Student), 0666|IPC_CREAT);    void *addr = shmat(sid, NULL, 0);    Student* stu = (Student *)addr;    strcpy(stu->name, "hchlqlz");    strcpy(stu->note, "AC是我的梦想");    shmdt(addr);    return 0;}

读并删除

#include<stdio.h>#include<sys/shm.h>struct Student{    char name[16];    char note[128];};int main(){    int sid = shmget(520, sizeof(Student), 0666);    void* addr = shmat(sid, NULL, 0);    Student* stu = (Student*) addr;    printf("学生姓名:%s\n", stu->name);    printf("学生备注:%s\n", stu->note);    shmdt(addr);    shmctl(sid, IPC_RMID, 0);       return 0;}
原创粉丝点击