#include
#include
#include
#include
#include
#include
#include
int main(int argc, const char *argv[])
{
key_t key;
if((key = ftok(".",'a')) == -1)
{
perror("ftok");
exit(-1);
}
printf("%d \n",(int)key);
return 0;
}
— 每个进程必须生成相同的key,因为通过相同的Key,才能找到同一个IPC对象;
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, const char *argv[])
{
char* addr;
int msgid;
if((shmid = shmget(IPC_PRIVATE,512,0666)) < 0)
{
perror("shmget");
exit(-1);
}
printf("%d \n",shmid);
return 0;
}
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, const char *argv[])
{
char* addr;
int msgid;
key_t key;
if((key = ftok(".",'a')) == -1)
{
perror("ftok");
exit(-1);
}
if((shmid = shmget(key,1024,IPC_CREAT|0666)) < 0)
{
perror("shmget");
exit(-1);
}
printf("%d \n",shmid);
return 0;
}
ftok:生成key值;
共享内存:不需要内存拷贝,效率最高;
shmget() :创建打开/创建;
— 首先要获得共享内存的ID后,对共享内存进行以下各种操作
— 每一个IPC对象都有一个唯一的ID,使用该ID可以对该对象做相应的操作;
作用:根据共享内存的ID,把一个共享内存映射到进程的地址空间,映射完以后,我们就可以像访问一个自己分配的内存空间一样取访问共享空间;
#include
#include
void *shmat(int shmid , const void *shmaddr, int shmflg);
例如: 在共享内存中存放键盘输入的字符串:
#include
#include
#include
#include
#include
#include
int main(int argc, const char *argv[])
{
char* addr;
int shmid;
key_t key;
if((key = ftok(".",'a')) == -1) ///获取 key值
{
perror("ftok");
exit(-1);
}
if((shmid = shmget(key,1024,IPC_CREAT|0666)) < 0) //打开/创建一个 共享文件
{
perror("shmget");
exit(-1);
}
printf("%d \n",shmid);
if((addr = (char*)shmat(shmid,NULL,0)) == (char*)-1 ) //映射一个共享文件
{
perror("shmat");
exit(-1);
}
fgets(addr,32,stdin);
return 0;
}
#include
#include
int shmdt (void *shmaddr);
#include
#include
int shmctl(int shmid,int cmd , struct shmid_ds *buf);
— 消息队列使用步骤:
#include
#include
int msgget(key_t key ,int msgflg);
— 打开消息队列的示例:
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, const char *argv[])
{
char* addr;
int msgid;
key_t key;
if((key = ftok(".",'a')) == -1)
{
perror("ftok");
exit(-1);
}
if((msgid = msgget(key,IPC_CREAT|0666))<0)
{
perror("msgid");
exit(-1);
}
return 0;
}
#include
#include
int msgsnd(int msgif, const void* msgp , size_t size);
— 通信双方首先定义好统一的消息格式;
— 用户根据应用需求定义结构体类型;
— 首成员类型为long ,代表消息类型(正整数);
— 其他成员都属于消息正文;
typedef struct
{
long mtype; //
char mtext[64];
}MSG;
#include
#include
int msgrcv (int msgid , void *msgp , size_t size , long msgtype , );
#include
#include
int msgctl (int msgid , int cmd , struct msqid_ds *buf );
第一个进程:
#include
#include
#include
#include
#include
#include
#include
typedef struct //消息队列的格式
{
long mtype; //消息类型
char mtext[64]; //消息正文
}MSG;
#define LEN (sizeof(MSG) - sizeof(long)) //正文长度
#define TypeA 100
#define TypeB 200
int main(int argc, const char *argv[])
{
key_t key;
int msgid;
MSG buf;
if((key = ftok(".",'q')) == -1) //得到key值
{
perror("ftok");
exit(-1);
}
if((msgid = msgget(key , IPC_CREAT|0666)) < 0) //打开/创建一个消息队列
{
perror("msgget");
exit(-1);
}
while(1)
{
buf.mtype = TypeB;
printf("intput : \n");
fgets(buf.mtext,64,stdin); //从键盘输入字符到消息队列中
msgsnd(msgid,&buf,LEN,0); //发送消息
if(strcmp(buf.mtext,"quit\n") == 0)break;
if(msgrcv(msgid,&buf,LEN,TypeA,0) < 0) //接收消息
{
perror("msgrcv");
exit(-1);
}
printf("recv from clientB : %s \n",buf.mtext);
if(strcmp(buf.mtext,"quit\n") == 0)
{
msgctl(msgid,IPC_RMID,0);//删除消息队列
exit(-1);
}
}
return 0;
}
第二个进程:
#include
#include
#include
#include
#include
#include
#include
typedef struct
{
long mtype;
char mtext[64];
}MSG;
#define LEN (sizeof(MSG) - sizeof(long))
#define TypeA 100
#define TypeB 200
int main(int argc, const char *argv[])
{
key_t key;
int msgid;
MSG buf;
if((key = ftok(".",'q')) == -1)
{
perror("ftok");
exit(-1);
}
if((msgid = msgget(key , IPC_CREAT|0666)) < 0)
{
perror("msgget");
exit(-1);
}
while(1)
{
if(msgrcv(msgid,&buf,LEN,TypeB,0) < 0)
{
perror("msgrcv");
exit(-1);
}
if(strcmp(buf.mtext,"quit\n") == 0)
{
msgctl(msgid,IPC_RMID,0);//删除消息队列
exit(-1);
}
printf("recb from cleintA : %s \n",buf.mtext);
buf.mtype = TypeA;
printf("intput : \n");
fgets(buf.mtext,64,stdin);
msgsnd(msgid,&buf,LEN,0);
if(strcmp(buf.mtext,"quit\n") == 0)break;
}
return 0;
}
— 两个进程 P1 P2分别申请资源A B 锁死的情况:
— 两个进程 P1 P2分别申请资源A B 使用System V 信号灯避免 锁死的情况:
— 使用System V 信号扽 使用步骤:
#include
#include
int semget (key_t key , int nsems , int semflg);
1、信号灯初始化
#include
#include
int semctl (int semid , int semnum , int cmd , .......);
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
— 信号灯P/V操作 ---- semop
#include
#include
int semop (int semid , struct sembuf* sops , unsigned nsops);
strct sembuf
{
short semnum;
short sem_op;
short sem_flg;
};
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define N 64
#define READ 0
#define WRITE 1
union semun // 信号灯的设置 格式
{
int val;
struct semid_ds *df;
unsigned short *array;
struct seminfo *buf;
};
void init_sem(int semid , int s[] ,int n) // 信号灯的初始化
{
int i;
union semun myun;
for(i = 0;i \n");
fgets(shmaddr,N,stdin);
if(strcmp(shmaddr,"quit\n") == 0)break;
pv(semid,READ,1);//对编号0的信号灯 V操作
}
kill(pid,SIGUSR1); //向子进程发送 SIGUSR1信号
}
_error2:
semctl(semid,0,IPC_RMID); //删除信号灯
_error1:
shmctl(semid,IPC_RMID,NULL); // 删除共享内存
return 0;
}