一.共享内存
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);
}