Linux-进程间通信-共享内存-消息队列

一.共享内存

1.int shmget//创建共享内存

2.void*shmat//将创建申请的物理内存空间映射到当前进程的地址空间中

3.shmdt//断开映射

4.shmct1//删除共享内存

5.删除共享内存:ipcrm -m +要删除的共享内存的id号

6.封装main函数与test函数

main程序:

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

int main()
{
    int shmid = shmget((key_t)2345,128,IPC_CREAT|0600);//128为给定字节的大小
    if ( shmid == -1 )
    {
        exit(1);
    }

    char* s = (char*)shmat(shmid,NULL,0);//NULL为出现在地址空间哪个位置赋为空,0为标志位,NULL和0为固定写法----->建立映射
    if ( s == (char*)-1)
    {
        exit(1);
    }

    sem_init();//创建 初始信号量
    while( 1 )
    {
        printf("input\n");
        char buff[128] = {0};
        fgets(buff,128,stdin);

        sem_p(SEM1);//对第一个下标进行p操作
        strcpy(s,buff);//将buff值放入s中
        sem_v(SEM2);//对第二个下标进行v操作
        if ( strncmp(buff,"end",3) == 0 )
        {

            break;
        }

    }
    shmdt(s);//断开映射
}

test程序:

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

int main()
{
    int shmid = shmget((key_t)2345,128,IPC_CREAT|0600);//128为给定字节的大小
    if ( shmid == -1 )
    {
        exit(1);
    }

    char* s = (char*)shmat(shmid,NULL,0);//NULL为出现在地址空间哪个位置赋为空,0为标志位,NULL和0为固定写法----->建立映射
    if ( s == (char*)-1)
    {
        exit(1);
    }

    sem_init();//初始化信号量
    while( 1)
    {
        sem_p(SEM2);//对第二个信号量进行p操作
        if ( strncmp(s,"end",3) == 0 )
        {
            break;
        }

        printf("s=%s\n",s);
        sem_v(SEM1);//对第一个信号量进行v操作
    }
    shmdt(s);//断开映射
    sem_destroy();//test程序结束后整体程序结束,故在test程序后进行销毁
    exit(0);
}

sem.h信号量.h程序:

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

enum INDEX{SEM1=0,SEM2};

union semun
{
    int val;
};

void sem_init();//创建并初始信号
void sem_p(int index);//要告诉第几个信号量进行p操作
void sem_v(int index);//要告诉第几个信号量进行v操作
void sem_destroy();//销毁

sem.c程序:

#include "sem.h"

static int semid = -1;

void sem_init()//创建并初始信号
{
    semid = semget((key_t)1234,2,IPC_CREAT|IPC_EXCL|0600);
    if ( semid == -1 )
    {
        semid = semget((key_t)1234,2,0600);
        if ( semid == -1 )
        {
            printf("semget err\n");
        }
    }
    else
    {
        int arr[2] = {1,0};
        for(int i = 0; i < 2; i++ )
        {
            union semun a;
            a.val = arr[i];
            if ( semctl(semid,i,SETVAL,a) == -1 )
            {
                printf("semctl init err\n");
            }
        }
    }
}
void sem_p(int index)
{
    struct sembuf buf;
    buf.sem_num = index;
    buf.sem_op = -1;//p
    buf.sem_flg = SEM_UNDO;

    if ( semop(semid,&buf,1) == -1 )
    {
        printf("op p err\n");
    }
}
void sem_v(int index)
{
    struct sembuf buf;
    buf.sem_num = index;
    buf.sem_op = 1;//v
    buf.sem_flg = SEM_UNDO;

    if ( semop(semid,&buf,1) == -1 )
    {
        printf("op v err\n");
    }

}
void sem_destroy()
{
    if ( semctl(semid,0,IPC_RMID) == -1 )//移除是所有的信号量全部移除,故不用特地指定下标,这个0是占位符
    {
        printf("semctl del\n");
    }
}

7.插入p,v操作使打印出来的使abcabc

共三个信号量初始值分别为1,0,0,具体插入位置如下:

二.消息队列

1.消息队列是结构体,都是由长整型组成的,且数据类型大小必须大于0,指定消息类型可以是1,2等等,当指定消息类型为0时,不区分消息类型。见下图:

2.msgget(key_t key(使用相同的整型值),int msqflg(标志位))//创建或获取一个消息队列

   msgsnd(int msgid,const void*msgp(消息体),size_t msgsz(数据的大小),int msgflg(标志位,一般为0))//添加消息

    ssize_t  msgrcv(int msqid,void*msgp(存放消息的一片空间即结构体),size_t msqsz(存放消息的空间能存多少字节的数据),long msqtyp(哪个类型的消息),int msqflg(标志位,一般为0))//读取消息

3.只查看消息队列:ipcs -q   只看共享内存:ipcs -m  只看信号量:ipcs -s

4.消息是一边加一边减,直到消息为0则阻塞住。

5.实例:

①添加消息队列

#include <string.h>
#include <sys/msg.h>

struct mess//消息对列必须为结构体
{
    long type;//必须为长整型,消息类型
    char buff[32];//数据大小,可以是结构体,整形等等
};

int main()
{
    int msgid = msgget((key_t)1234,IPC_CREAT|0600);//获取消息队列,msgid为返回值
    if ( msgid == -1 )
    {
        printf("msgid err\n");
        exit(1);
    }

    struct mess dt;
    dt.type = 2;//2类型消息
    strcpy(dt.buff,"hello2");//将hello2拷贝到dt.buff中

    msgsnd(msgid,(void*)&dt,32,0);//添加消息队列,32不包含长整型,只为数据大小
}

②读取消息

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/msg.h>

struct mess//消息对列必须为结构体
{
    long type;//必须为长整型,消息类型
    char buff[32];//数据大小,可以是结构体,整形等等
};

int main()
{
    int msgid = msgget((key_t)1234,IPC_CREAT|0600);//获取消息队列,msgid为返回值
    if ( msgid == -1 )
    {
        printf("msgid err\n");
        exit(1);
    }

    struct mess dt;
    msgrcv(msgid,&dt,32,0,0);//读取消息,存放消息的空间为%dt,32为数据大小,第一个0为可以读取任意类型的消息,第二个0为标志位
    printf("recv:%s\n",dt.buff);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值