linux c 多进程互斥与共享内存的实践问题
问题: 三个进程P1、P2、P3互斥使用一个包含N(N>0)个单元的缓冲区。P1每次用produce()生成一个正整数并送入缓冲区某一空单元中;P2每次用getodd()从该缓冲区中取出一个奇数并用countodd()统计奇数个数;P3每次用geteven()从该缓冲区中取出一个偶数并用counteven()统计偶数个数。1.设计问题1)设计多进程分别执行不同代码块..
·
问题:
三个进程P1、P2、P3互斥使用一个包含N(N>0)个单元的缓冲区。P1每次用produce()生成一个正整数并送入缓冲区某一空单元中;P2每次用getodd()从该缓冲区中取出一个奇数并用countodd()统计奇数个数;P3每次用geteven()从该缓冲区中取出一个偶数并用counteven()统计偶数个数。
1.设计问题
1)设计多进程分别执行不同代码块
2)使用信号量PV操作控制多进程进行互斥执行
3)使用共享内存实现缓冲区
2.解决问题
1)实现多进程分别执行不同代码块
/*
============================================================================
Name : createMultiprocess.c
Author : lingo
Version :
CreateDate : 2018下午9:03:24
============================================================================
*/
#include <stdio.h>
#include <unistd.h>
int main(int arg,char* argv[]){
int tog;
// 设置fork返回值
pid_t pid;
// 创建多个子进程,childNum为子进程个数
int i,childNum;
for(i = 0,childNum = 3;i < childNum;i++){
pid = fork();
// 是父进程 continue ,for()五次,若是子进程,break该for循环,即子进程无需经历for循环
if(pid==0 || pid<0) break;
}
if(pid < 0){
printf("ERROR:fork child process failure\n");
}
// 子进程循环体
else if(pid == 0){
//共同执行代码
tog = 10;
//分别执行代码区
if(i == 0){
printf("i=%i tog=%u\n",i,tog);
}else if(i == 1){
printf("i=%i tog=%u\n",i,tog);
}else if(i == 3){
printf("i=%i tog=%u\n",i,tog);
}
printf("create sub process id: %d, parent id: %d\n", getpid(), getppid());
// pause 子进程进入睡眠,即阻塞住所有子进程,直到被信号(signal)所中断.
//while(1) pause();
}
// 父进程执行体
else{
//tog = 10;
printf("tog=%u",tog);
printf("Parent process %d sleep 1 s\n", getpid());
sleep(3);
}
return 0;
}
2)实现初始化信号量和对信号量PV操作,封装为mysem.h头文件供使用
/*
* mysem.h
*
* Created on: 2018年10月19日
* Author: lin
*/
#ifndef MYSEM_H_
#define MYSEM_H_
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
// 定义信号量结构
union semaphore{
int val;
struct semid_ds *buf;
unsigned short *array;
};
/*声明函数*/
/*初始化信号量
* sem_id 信号量的标识id
* init_val 信号量的pv操作的数值
* */
int init_sem(int sem_id,int init_val){
union semaphore sem;
sem.val = init_val; //设置初值
if(semctl(sem_id,0,SETVAL,sem)==-1){
printf("init semaphore error \n");
return -1;
}
return 0;
}
/*删除指定标识id的信号量*/
int del_sem(int sem_id){
union semaphore sem;
if(semctl(sem_id,0,IPC_RMID,sem)==-1){
return -1;
}
return 0;
}
/* 将指定标识的信号量-1 若信号量值为0时执行p操作的进程会处于阻塞等待的状态*/
int P(int sem_id){ //信号量-1
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = -1;
sem_b.sem_flg = SEM_UNDO;
if(semop(sem_id,&sem_b,1)==-1){
return -1;
}
return 0;
}
/* 将指定标识的信号量+1 若型号量的值为0执行完v操作后 唤醒处于阻塞等待的进程处于就绪状态等待cpu调用*/
int V(int sem_id){ //信号量+1
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = 1;
sem_b.sem_flg = SEM_UNDO;
if(semop(sem_id,&sem_b,1)==-1){
return -1;
}
return 0;
}
#endif /* MYSEM_H_ */
3)缓冲区结构体设计:
#define BUFF_SIZE 255
typedef struct{
int length; // 缓冲区长度
int data[BUFF_SIZE]; //缓冲区大小
int oddNum; // 记录被get掉的奇数个数
int evenNum; // 记录被get掉的偶数个数
}Buff;
4)共享内存
#include <sys/shm.h>
#define MY_SHM_ID 95551 //不同值对应不同共享内存,
.......
int main(){
.......
int shmid = shmget(MY_SHM_ID,sizeof(Buff),0666|IPC_CREAT);
if(shmid == -1){
printf("error semget / shmget");
}
// 映射共享内存
buff = (Buff*)shmat(shmid,NULL,0);
// 初始化变量
buff->length = 0;
buff->oddNum = 0;
buff->evenNum = 0;
.......
return 0;
}
3.produce(),getodd(),countodd(),geteven(),counteven()函数设计:
void produce(Buff *buff){
int temp = random(10);
buff->data[buff->length] = temp;
buff->length++;
printf("produce a num : %i \n",temp);
// 每生产一个睡眠1s
sleep(1);
}
void getodd(Buff *buff){
for(int i = 0; i < buff->length; i++){
if(1 == (buff->data[i]%2)){
printf("getodd num is : %i \n",buff->data[i]);
// 将索引的值删除,所有索引后的退位
for(int j = i; j < buff->length -1; j++){
buff->data[j] = buff->data[j+1];
}
buff->length--;
break;
}
}
}
void countodd(Buff *buff){
buff->oddNum++;
printf("Now the oddNum=%i \n",buff->oddNum);
}
void geteven(Buff *buff){
// buff 长度为1
for(int i = 0; i < buff->length; i++){
if(0 == (buff->data[i]%2)){
printf("geteven num is : %i \n",buff->data[i]);
// 将索引的值删除,所有索引后的退位
for(int j = i; j < buff->length -1; j++){
buff->data[j] = buff->data[j+1];
}
buff->length--;
break;
}
}
}
void counteven(Buff *buff){
buff->evenNum++;
printf("Now the evenNum=%i \n",buff->evenNum);
}
3. 详细设计
源码地址:源码
更多推荐
已为社区贡献2条内容
所有评论(0)