2023/3/7 消息队列、共享内存与信号灯集练习
1.用消息队列 实现AB进程对话,要求AB进程能够随时收发。
提示:多进程,多线程。
A端:
#include "head.h"
#define MAXSIZE_MSG 128
typedef void (*sighandler_t)(int);
void handler(int sig)
{
while(waitpid(-1,NULL,WNOHANG) > 0);
}
struct msgbuf
{
long mtype;//消息类型
char mtext[MAXSIZE_MSG];//消息内容,自定义大小
};
int main(int argc, const char *argv[])
{
sighandler_t s = signal(17,handler);
if(SIG_ERR == s)
{
ERR_MSG("signal");
return -1;
}
key_t key = ftok("/home/ubuntu/",1);
if(key < 0)
{
ERR_MSG("ftok");
return -1;
}
printf("key = %#x\n",key);
//获取消息队列的shmid
int msqid = msgget(key,IPC_CREAT|0664);
if(msqid < 0)
{
ERR_MSG("msgget");
return -1;
}
printf("msqid = %d\n",msqid);
system("ipcs -q");
pid_t cpid = fork();
if(cpid > 0)
{
//发送数据
struct msgbuf snd;
while(1)
{
printf("输入消息类型:");
scanf("%ld",&snd.mtype);
while(getchar() != 10);
printf("输入消息:");
scanf("%s",snd.mtext);
while(getchar() != 10);
//阻塞方式发送
if(msgsnd(msqid,&snd,sizeof(snd.mtext),0) < 0)
{
ERR_MSG("msgsnd");
return -1;
}
if(strcmp(snd.mtext,"quit") == 0)
{
break;
}
printf("msgsnd success\n");
}
system("ipcs -q");
//删除消息队列
if(msgctl(msqid,IPC_RMID,NULL) < 0)
{
ERR_MSG("msgctl");
return -1;
}
kill(cpid,9);
}else if(0 == cpid)
{
//读取数据
struct msgbuf rcv;
while(1)
{
if(msgrcv(msqid,&rcv,sizeof(rcv.mtext),100,0) < 0)
{
ERR_MSG("msgrv");
return -1;
}
if(strcmp(rcv.mtext,"quit") == 0)
{
printf("对端B已退出\n");
break;
}
printf("\nmtype = %ld,mtext = %s\n",rcv.mtype,rcv.mtext);
}
kill(getppid(),9);
exit(0);
}else
{
ERR_MSG("fork");
return -1;
}
return 0;
}
B端
#include "head.h"
#define MAXSIZE_MSG 128
typedef void (*sighandler_t)(int);
void handler(int sig)
{
while(waitpid(-1,NULL,WNOHANG) > 0);
}
struct msgbuf
{
long mtype;//消息类型
char mtext[MAXSIZE_MSG];//消息内容,自定义大小
};
int main(int argc, const char *argv[])
{
sighandler_t s = signal(17,handler);
if(SIG_ERR == s)
{
ERR_MSG("signal");
return -1;
}
key_t key = ftok("/home/ubuntu/",1);
if(key < 0)
{
ERR_MSG("ftok");
return -1;
}
printf("key = %#x\n",key);
//获取消息队列的shmid
int msqid = msgget(key,IPC_CREAT|0664);
if(msqid < 0)
{
ERR_MSG("msgget");
return -1;
}
printf("msqid = %d\n",msqid);
system("ipcs -q");
pid_t cpid = fork();
if(cpid > 0)
{
//发送数据
struct msgbuf snd;
while(1)
{
printf("输入消息类型:");
scanf("%ld",&snd.mtype);
while(getchar() != 10);
printf("输入消息:");
scanf("%s",snd.mtext);
while(getchar() != 10);
//阻塞方式发送
if(msgsnd(msqid,&snd,sizeof(snd.mtext),0) < 0)
{
ERR_MSG("msgsnd");
return -1;
}
if(strcmp(snd.mtext,"quit") == 0)
{
break;
}
printf("msgsnd success\n");
}
system("ipcs -q");
//删除消息队列
if(msgctl(msqid,IPC_RMID,NULL) < 0)
{
ERR_MSG("msgctl");
return -1;
}
kill(cpid,9);
}else if(0 == cpid)
{
//读取数据
struct msgbuf rcv;
while(1)
{
if(msgrcv(msqid,&rcv,sizeof(rcv.mtext),200,0) < 0)
{
ERR_MSG("msgrv");
return -1;
}
if(strcmp(rcv.mtext,"quit") == 0)
{
printf("对端B已退出\n");
break;
}
printf("\nmtype = %ld,mtext = %s\n",rcv.mtype,rcv.mtext);
}
kill(getppid(),9);
exit(0);
}else
{
ERR_MSG("fork");
return -1;
}
return 0;
}
2.创建两个进程,定义一个共享内存,内存中存储char str[10]= “1234567”;要求如下
1.A循环打印str;
2.B循环倒置str; 不能使用辅助数组;
3.要求出现的结果没有乱序,只能出现 1234567 7654321
4.不允许使用sleep函数
#include "head.h"
void strRev(char *p)
{
int i,j;
char temp;
i=0;
j=strlen(p)-1;
while(i<j)
{
temp = *(p+i);
*(p+i) = *(p+j);
*(p+j) = temp;
i++;
j--;
}
}
int main(int argc, const char *argv[])
{
//创建key值
key_t key = ftok("/home/ubuntu/",10);
if(key < 0)
{
ERR_MSG("ftok");
return -1;
}
//获取semid
int semid = semget(key,2,IPC_CREAT|0664);
if(semid < 0)
{
ERR_MSG("semget");
return -1;
}
printf("semid = %d\n",semid);
system("ipcs -s");
//设置信号灯的值
unsigned short arr[2] = {0,1};
if(semctl(semid,0,SETALL,arr) < 0)
{
ERR_MSG("semctl");
return -1;
}
//创建共享内存
int shmid = shmget(key,128,IPC_CREAT|0664);
if(shmid < 0)
{
ERR_MSG("shmget");
return -1;
}
//映射到用户空间
void* shmaddr = shmat(shmid,NULL,0);
if((void*)-1 == shmaddr)
{
ERR_MSG("shmat");
return -1;
}
char* str = (char*)shmaddr;
strcpy(str,"1234567");
pid_t cpid = fork();
if(cpid > 0)
{
struct sembuf sop;
char*p = (char*)shmaddr;
while(1)
{
sop.sem_num = 1;//操作1号灯
sop.sem_op = -1;//P操作
sop.sem_flg = 0;//阻塞方式
if(semop(semid,&sop,1) < 0)
{
ERR_MSG("semop");
return -1;
}
printf("%s\n",p);
sop.sem_num = 0;//操作0号灯
sop.sem_op = +1;//V操作
sop.sem_flg = 0;//阻塞方式
if(semop(semid,&sop,1) < 0)
{
ERR_MSG("semop");
return -1;
}
}
}else if(0 == cpid)
{
struct sembuf sop;
char* p = (char*)shmaddr;
while(1)
{
//P操作
sop.sem_num = 0;//控制0号灯
sop.sem_op = -1;//P操作
sop.sem_flg = 0;//阻塞方式
if(semop(semid,&sop,1) < 0)
{
ERR_MSG("semop");
return -1;
}
strRev(p);
sop.sem_num = 1;//控制1号灯
sop.sem_op = +1;//V操作
sop.sem_flg = 0;//阻塞方式
if(semop(semid,&sop,1) < 0)
{
ERR_MSG("semop");
return -1;
}
}
}else
{
ERR_MSG("fork");
return -1;
}
//删除信号灯集
if(semctl(semid,0,IPC_RMID) < 0)
{
ERR_MSG("semctl");
return -1;
}
//删除共享内存
if(shmctl(shmid,IPC_RMID,NULL) < 0)
{
ERR_MSG("shmctl");
return -1;
}
return 0;
}