进程间通信 内存共享信号量实例理解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/s564200489/article/details/50506401

申请内存:

int shmget(key_t key, size_t size, int shmflg);

其中key为钥匙,两进程通过同一个钥匙找到内核中的共享内存,可通过

key_t ftok(const char *pathname, int proj_id)

得到key,也可通过强制转换自行制定数值。
size为申请共享内存空间的大小(B)
shmflg为标志
返回值为共享内存的标示符。

内存映射:

void *shmat(int shmid, const void *shmaddr, int shmflg);

其中shmid为共享内存的ID。
shmaddr为映射向进程的地址,一般填NULL让系统指配
返回值为进程内映射共享内粗的地址。

这样通过操作进程内映射地址(内存),便可以在共享内存中写入或读取数据。


但该过程是不受控制的,因此我们需要通过阻塞来控制进程的执行。

信号量

信号量与共享内存类似,也是在内核空间中申请一段内存储存数据

申请信号量:

int semget(key_t key, int nsems, int semflg);

其中 key为钥匙,两进程通过钥匙找到同一个信号量
nsems 为申请的信号量的个数
返回值为信号量标示符

操作信号量:

int semctl(int semid, int semnum, int cmd, ...);

其中semnum,为第semnum位信号量,从0开始
cmd为指定的操作
后面跟对应数据

int semop(int semid, struct sembuf *sops, unsigned nsops);

其中

struct sembuf
{
      unsigned short sem_num;  /* 第sem_num位信号量 */
      short sem_op;   /* 操作量 */
      short  sem_flg;  /* 标志对应操作 */
}

nsops为,对nsops个信号量进行该操作

因为信号量的值不能小于0,因此可以通过semop函数进行阻塞。

实例:

输入程序:

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

int main()
{
    int running =1;
    int shid;
    int semid;
    int value;
    char *sharem=NULL;
    struct sembuf sem_b,sem_c;
    sem_b.sem_num=1;
    sem_b.sem_flg=SEM_UNDO;
    sem_c.sem_num=0;
    sem_c.sem_flg=SEM_UNDO;
    if((semid=semget((key_t)123456,2,0666|IPC_CREAT))==-1)//申请信号量
    {
        perror("semget");
        exit(1);
    }
    shid=shmget((key_t)654321,(size_t)2048,0600|IPC_CREAT);//申请共享内存
    if(shid==-1)
        exit(1);
    sharem=shmat(shid,NULL,0);
    if(sharem==NULL)
        exit(1);
    semctl(semid,1,SETVAL,1);//初始化将自己的信号量设为1
    semctl(semid,0,SETVAL,0);//将读取进程的信号量设为0使之堵塞
    while(running)
    {
        sem_b.sem_op=-1;//设为-1
        if(semop(semid,&sem_b,1)==-1)//让信号量0加-1,若此时信号量为0则无法-1则阻塞
        {
                exit(1);
        }
        printf("write data operate\n");
        printf("please input something:");
        scanf("%s",sharem);

        semctl(semid,0,SETVAL,1);//输入完毕将读取信号信号量置1使之不堵塞
        semctl(semid,1,SETVAL,0);//将自己的信号量设为0,使自身堵塞无法再写入
        if(strcmp(sharem,"end")==0)
            running--;
    }
    shmdt(sharem);
    return 0;

}   

接收程序:

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

int main()
{
    int running =1;
    int shid;
    int semid;
    int value;
    char *sharem=NULL;
    struct sembuf sem_b,sem_c;
    sem_b.sem_num=1;
    sem_b.sem_flg=SEM_UNDO;
    sem_c.sem_num=0;
    sem_c.sem_flg=SEM_UNDO;
    if((semid=semget((key_t)123456,2,0666|IPC_CREAT))==-1)
    {
        perror("semget");
        exit(1);
    }
    shid=shmget((key_t)654321,(size_t)2048,0600|IPC_CREAT);
    if(shid==-1)
        exit(1);
    sharem=shmat(shid,NULL,0);
    if(sharem==NULL)
        exit(1);
    semctl(semid,0,SETVAL,1);
    //初始化,使自己堵塞,等待输入进程的输入
    while(running)
    {
        sem_b.sem_op=-1;
        if(semop(semid,&sem_b,1)==-1)//同输入进程
        {
            exit(1);
        }
        printf("read data operate\n");
        printf("%s\n",sharem);

        semctl(semid,0,SETVAL,0);//将输入进程的信号量置1
        semctl(semid,1,SETVAL,1);//将自己堵塞

        if(strcmp(sharem,"end")==0)
            running--;
    }
    shmdt(sharem);
    if(shmctl(shid,IPC_RMID,0)!=0)//销毁共享内存
    {
        exit(1);
    }
    if(semctl(semid,0,IPC_RMID,0)!=0)//销毁信号量
    {
        exit(1);
    }
    return 0;

}   

猜你喜欢

转载自blog.csdn.net/s564200489/article/details/50506401
今日推荐