1.使用消息队列,完成对结构体数据的传输
源码:
msgsnd.c
#include <myhead.h>
typedef struct{
long msgtype;
struct{
char name[10];
char age[5];
};
}Msginfo;
#define MSGSZ (sizeof(Msginfo) - sizeof(long))
int main(int argc, const char *argv[])
{
//创建、定义key;
key_t key;
if((key = ftok("/", 't')) == -1){
perror("ftok error");
return -1;
}
//创建、定义消息队列
int msgid;
if((msgid = msgget(key, IPC_CREAT | 0664)) == -1){
perror("msgget error");
return -1;
}
//发送消息队列
Msginfo msg = {.msgtype = 10};
while(1){
//输入正文内容
printf("请输入姓名:\n");
fgets(msg.name, sizeof(msg.name), stdin);
msg.name[strlen(msg.name) - 1] = '\0';
printf("请输入年龄:\n");
fgets(msg.age, sizeof(msg.age), stdin);
//发送
if(msgsnd(msgid, &msg, MSGSZ, 0) == -1){
perror("msgsnd error");
return -1;
}
if(strcmp(msg.name, "quit") == 0){
break;
}
}
//删除队列
msgctl(msgid, IPC_RMID, NULL);
return 0;
}
msgrcv.c
#include <myhead.h>
typedef struct{
long msgtype;
struct{
char name[10];
char age[5];
};
}Msginfo;
#define MSGSZ (sizeof(Msginfo) - sizeof(long))
int main(int argc, const char *argv[])
{
//创建、定义key;
key_t key;
if((key = ftok("/", 't')) == -1){
perror("ftok error");
return -1;
}
//创建、定义消息队列
int msgid;
if((msgid = msgget(key, IPC_CREAT | 0664)) == -1){
perror("msgget error");
return -1;
}
//接收消息队列
Msginfo msg = {.msgtype = 10};
while(1){
//接收
if(msgrcv(msgid, &msg, MSGSZ, 0, 0) == -1){
perror("msgrcv error");
return -1;
}
printf("姓名:%s 年龄:%s\n", msg.name, msg.age);
if(strcmp(msg.name, "quit") == 0){
break;
}
}
//删除队列
msgctl(msgid, IPC_RMID, NULL);
return 0;
}
2.使用三个信号灯集,完成三个进程间的同步,使用三个进程输出:ABCABCABC...
源码:
sem.h
#ifndef __SEM_H__
#define __SEM_H__
int sem__init(); //创建一个信号灯集
int P(int semid, int semnum); //申请资源,将semnum资源减一
int V(int semid, int semnum); //释放资源,将semnum资源加一
int sem_del(int semid); //删除一个信号灯集
#endif /* SEM_H */
sem.c
#include <myhead.h>
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) */
};
//定义设置灯的值的函数
//给semid灯集的semno的这个灯值设置为value
void init_semnum_value(int semid, int semno, int value)
{
union semun sem;
sem.val = value;
//设置信号灯的值
semctl(semid, semno, SETVAL, sem);
}
int sem__init(int count) //创建一个信号灯集
{
//1、申请key值
key_t key;
if ((key = ftok("/", 'm')) == -1)
{
perror("ftok");
return -1;
}
//2、创建信号量
int semid;
if ((semid = semget(key, count, IPC_CREAT|IPC_EXCL|0664)) == -1)
{
if (errno == EEXIST) //说明信号灯集已经存在,直接打开即可
{
semid = semget(key, count, IPC_CREAT|0664);
}
else
{
perror("semget");
return -1;
}
}
else
{
//原本不存在,重新创建一个需要对其初始化
init_semnum_value(semid, 0, 0); //0号灯value初始化为0
init_semnum_value(semid, 1, 0); //1号灯value初始化为0
init_semnum_value(semid, 2, 1); //2号灯value初始化为1
}
return semid; //将申请的信号灯集id返回
}
int P(int semid, int semnum) //申请资源,将semnum资源减一
{
struct sembuf buf; //定义有关灯操作的结构体
buf.sem_num = semnum; //表明要更改的灯的编号
buf.sem_op = -1; //表明要申请资源
buf.sem_flg = 0; //阻塞等待
//调用op函数
semop(semid, &buf, 1);
return 0;
}
int V(int semid, int semnum) //释放资源,将semnum资源加一
{
struct sembuf buf; //定义有关灯操作的结构体
buf.sem_num = semnum; //表示要更改的灯的编号
buf.sem_op = 1; //表明要释放资源
buf.sem_flg = 0; //阻塞等待
//调用op函数
semop(semid, &buf, 1);
return 0;
}
int sem_del(int semid) //删除一个信号灯集
{
//删除信号灯集
return semctl(semid, 0, IPC_RMID, 0);
}
a.c
#include <myhead.h>
#include "sem.h"
#define SHMSZ 4096
#define COUNT 3
int main(int argc, const char *argv[])
{
//1、定义一个信号量id
int semid = sem__init(COUNT);
//定义key值
key_t key;
if ((key = ftok("/", 'm')) == -1)
{
perror("ftok");
return -1;
}
//定义共享内存id
int shmid;
//创建共享内存
if ((shmid = shmget(key, SHMSZ, IPC_CREAT|0664)) == -1)
{
perror("shmget");
return -1;
}
//将创建好的共享内存映射到该程序中
char *shmaddr;
shmaddr = shmat(shmid, NULL, 0);
while (1)
{
//2、申请2号灯的资源
P(semid, 2);
//向共享内存中读取数据
shmaddr[0] = 'A';
//3、释放0号灯的资源
V(semid, 0);
}
//取消映射
shmdt(shmaddr);
return 0;
}
b.c
#include <myhead.h>
#include "sem.h"
#define SHMSZ 4096
int main(int argc, const char *argv[])
{
//1、定义一个信号量id
int semid = sem__init();
//定义key值
key_t key;
if ((key = ftok("/", 'm')) == -1)
{
perror("ftok");
return -1;
}
//定义共享内存id
int shmid;
//创建共享内存
if ((shmid = shmget(key, SHMSZ, IPC_CREAT|0664)) == -1)
{
perror("shmget");
return -1;
}
//将创建好的共享内存映射到该程序中
char *shmaddr;
shmaddr = shmat(shmid, NULL, 0);
//打印地址
/*printf("shmaddr = %d\n", *shmaddr);*/
while (1)
{
//2、申请0号灯的资源
P(semid, 0);
//向共享内存中读取数据
shmaddr[1] = 'B';
//3、释放1号灯的资源
V(semid, 1);
}
//取消映射
shmdt(shmaddr);
//删除共享内容
shmctl(shmid, IPC_RMID, NULL);
//4、删除信号灯集
sem_del(semid);
return 0;
}
c.c
#include <myhead.h>
#include "sem.h"
#define SHMSZ 4096
#define COUNT 3
int main(int argc, const char *argv[])
{
//1、定义一个信号量id
int semid = sem__init(COUNT);
//定义key值
key_t key;
if ((key = ftok("/", 'm')) == -1)
{
perror("ftok");
return -1;
}
//定义共享内存id
int shmid;
//创建共享内存
if ((shmid = shmget(key, SHMSZ, IPC_CREAT|0664)) == -1)
{
perror("shmget");
return -1;
}
//将创建好的共享内存映射到该程序中
char *shmaddr;
shmaddr = shmat(shmid, NULL, 0);
while (1)
{
sleep(1);
//2、申请1号灯的资源
P(semid, 1);
shmaddr[2] = 'C';
shmaddr[3] = '\0';
int i = 0;
while (shmaddr[i] != '\0')
{
printf("%c", shmaddr[i++]);
fflush(stdout);
sleep(1);
}
//3、释放2号灯的资源
V(semid, 2);
}
//取消映射
shmdt(shmaddr);
return 0;
}