• 进程间通信IPC:消息队列,信号量,共享内存


    2015.3.4
    星期三 阴天

    进程间通信:IPC

    文件对象:记录文件描述符,文件开关等

    IPC标示符:系统全局的流水号
    两个进程要通信,打开的是唯一的对象进行通讯,通过key操作

    XSI IPC:消息队列,信号量,共享内存。

    ipcs 查看ip对象共享内存,信号量,消息队列等信息
    ipcrm 删除一个IP对象

    Linux为用户提供了完善的,强大的网络功能
    完善的内置网络:其他操作系统不包含如此紧密的和内核结合在一起的网络部分

    共享内存标示符的获取有两种方法:ftok(pathname,id)另一个是KEY = IPC_CREATE

    共享内存的创建,映射,读取状态等操作:(下面这个程序很短,但是基本包含了大部分共享内存函数的应用,程序入门非常好)

    消息队列的实例程序;

    #include <unistd.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>

    #define KEY 1234
    #define TEXT_SIZE 48

    struct msgbuffer
    {
    long mtype;
    char mtext[TEXT_SIZE];
    }msgp;

    int mian(int argc, char **argv)
    {
    int msqid;
    msqid = msgget(KEY, IPC_CTEAT | 0600); 建立消息队列

    if(fork() == 0)
    {
    msgp.mtype = 1;
    strcpy(msgp.mtext,"hi! I am child process! ");
    msgsnd(msqid,&msgp,TEXT_SIZE,0); 传送消息至队列
    return ;
    }

    else
    {
    sleep(3); 等子进程执行完毕
    msgrcv(msqid,&msgp,TEXT_SIZE,0,0); 接收队列的信息
    printf("parent receive mtext : %s",msgp.mtext);
    msgctl(msqid,IPC_RMID,NULL): 删除消息队列
    }
    }


    #include <unistd.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>

    #define KEY 1234
    #define SIZE 1024

    int main(int argc, char **argv)
    {
    int shmid;
    char *shmaddr;
    struct shmid_ds buf;

    shmid = shmget(KEY,SIZE,IPC_CREAT | 0600); 建立共享内存

    if(fork() == 0) 子进程
    {
    shmaddr = (char *)shmat(shmid,NULL,0); 子进程映射共享内存
    strcpy(shmaddr,"hi! I an child process! "); 对共享内存写入数据
    shmdt(shmaddr); 释放子进程虚拟内存
    return;
    }

    { 父进程
    sleep(3); 等待子进程执行完毕
    shmctl(shmid,IPC_STAT,&buf); 取得共享内存的状态
    printf("shm_segsz = %d bytes ",shm_segsz);
    printf("shm_cpid = %d bytes ",shm_cpid);
    printf("shm_lpid = %d bytes ",shm_lpid);

    shmaddr = (char *)shmat(shmid,NULL,0); 父进程映射共享内存
    printf("%s",shmaddr); 显示共享内存内容
    shmdt(shmaddr); 释放父进程虚拟内存
    shmctl(shmid,IPC_RMID,NULL); 删除共享内存
    }
    }

    共享内存的另一个程序:

    #include <sys/shm.h>
    #include <sys/stat.h>
    #include <sys/ipc.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <fcntl.h>

    #define BUFSZ 2048

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

    if((shmid = shmget(IPC_PRIVATE,BUFSZ,0666)) < 0); IPC_PRIVATE是指定键,保证了能创建一个新的IPC,缺点是获得的标识符写入
    { 了文件中,用户用的时候需要进入文件读取
    perror("shmget");
    exit(-1);
    }

    printf("###create shared - memory:%d ",shmid);

    system("ipcs -m | grep 666"); 相当于执行 ipcs -m

    if((shmaddr = (char *)shmat(shmid,NULL,0))<(char *)0)
    {
    perror("shmat");
    exit(-1);
    }


    printf("###create shared - memory ");

    system("ipcs -m | grep 666");

    if((shmdt(shmaddr)) < 0)
    {
    perror("shmdt");
    exit(-1);
    }

    printf("###create shared - memory ");

    system("ipcs -m | grep 666");

    shmctl(shmid, IPC_RMID, NULL); 删除共享内存段
    printf("###create shared - memory ");

    system("ipcs -m | grep 666");

    return 0;

    }


    创建共享内存和信号灯并初始化,创建子进程,父进程读取标准输入并写入共享内存,子进程打印共享内存中的内容,双方通过信号灯进行同步;

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

    #define READ 0
    #define WRITE 1

    union semun 这个联合体需要自己定义
    {
    int val;
    struct semid_ds *buf;
    unsigned short *array;
    struct seminfo *_buf;
    };

    int shmid; 定义的一些全局变量:
    int semid;
    pid_t pid;

    int main()
    {
    key_t key;
    char *shmaddr;
    union semun myun;
    struct sembuf buf;

    if((key = ftok("./",'a')) == -1) 获得键值
    {
    perror("faile to ftok");
    exit(-1);
    }

    if((shmid = shmget(key,64,IPC_CREAT|0666)) < 0) 建立共享内存,如果存在就取内存ID
    {
    perror("fail to shmget");
    exit(-1);
    }

    shmaddr = (char*)shmat(shmid,NULL,0); 映射虚拟内存,下面调用fork(),会将映射继承到子进程中,这是创建进程间相同映射的一种方式

    if((semid = semget(key,2,IPC_CREAT|0666)) < 0) 创建信号集,信号集中有两个信号
    {
    perror("fail to semget");
    exit(-1);
    }

    myun.val = 0; 这是一个初始化操作,表示信号量的个数
    semctl(semid,READ,SETVAL,myun);
    myun.val = 1;
    semctl(semid,WRITE,SETVAL,myun);


    if((pid = fork()) < 0) 创建子进程
    {
    perror("fail to fork");
    exit(-1);
    }
    else if(pid == 0)
    {
    buf.sem_num = READ; 信号个数0
    buf.sem_op = -1; p操作,信号量小于等于0则阻塞 (sem_wait()函数) 3.在2之后开始执行
    buf.sem_flg = 0;
    semop(semid,&buf,1);
    printf("read from shm : %s",shmaddr);
    buf.sem_num = WRITE; 信号个数1
    buf.sem_op = 1; v操作 (sem_post()函数)将信号 4.将信号量个数置0,子进程等待。
    buf.sem_flg = 0;
    semop(semid,&buf,1);
    }
    else
    {
    buf.sem_num = WRITE; 信号个数
    buf.sem_op = -1; p操作 (sem_post()函数) 1.执行
    buf.sem_flg = 0;
    semop(semid,&buf,1);
    printf("write to shm : ");
    fgets(shmaddr,64,stdin);
    buf.sem_num = READ; 信号个数0
    buf.sem_op = 1; V操作 (sem_wait()函数) 2.唤醒子进程的等待程序
    buf.sem_flg = 0;
    semop(semid,&buf,1);
    }

    return 0;
    }

    ***************************************************************************************************************************************************************
    ***************************************************************************************************************************************************************
    ***************************************************************************************************************************************************************
    ***************************************************************************************************************************************************************

  • 相关阅读:
    不会吧不会吧,还有开发不会Java填充PDF模板数据的,赶紧看看吧
    关于Redis分布式锁这一篇应该是讲的最好的了,先收藏起来再看!
    iOS-----后台运行
    iOS-----使用GCD实现多线程
    iOS-----线程同步与线程通信
    iOS-----多线程之NSThread
    iOS-----MFMessageCompose 和 MFMailComposeViewController的使用方法
    iOS-----使用AddressBookUI管理联系人
    iOS-----使用addressBook管理联系人之修改联系人
    iOS-----简易地CocoaAsyncSocket使用
  • 原文地址:https://www.cnblogs.com/cnlg/p/4314637.html
Copyright © 2020-2023  润新知