#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <wait.h>
//共享内存部分
#define SHM_SIZE 8*32 //共享内存总大小
#define SHM_BUF_SIZE SHM_SIZE - sizeof(int)*2 //共享内存实际存储字符数组大小
#define SHM_FLAGS IPC_CREAT | SHM_W |SHM_R //创建共享内存的MODE
#define SHM_KEY 1234 //共享内存对应唯一的key值
#define SHM_KEY_B 1235 //共享内存对应唯一的key值
//信号量部分
//信号量对应的唯一的字符串
#define A_FULL "a_full"
#define A_EMPTY "a_empty"
#define B_FULL "b_full"
#define B_EMPTY "b_empty"
#define SEM_ORDER "SEM_ORDER"
#define SEM_FLAGS 0666 //创建信号量的MODE
//杂项
#define A_TURN 0 //该A了
#define B_TURN 1 //该B了
#define OUT_PUT_FILE "../output.txt" //输出文件
#define F_NAME "source1" //输入文件
#define BUFF_SIZE 8 //临时的buffer大小,用来接收从文件读取的字符
typedef struct shm_struct_t{
//共享内存结构体
int size;
int flag;
char buf[SHM_BUF_SIZE];
}shm_struct;
//两个辅助函数
int my_strncpy(shm_struct *dest, char* source,int size);
int my_tolower(char * str,int len);
int main(int argc,char ** argv) {
pid_t child;
int shm_id,shm_id_b;
sem_t *sem_order,*a_full,*a_empty,*b_full,*b_empty;
sem_unlink(SEM_ORDER);
sem_unlink(A_EMPTY);
sem_unlink(A_FULL);
sem_unlink(B_EMPTY);
sem_unlink(B_FULL);
//开始创建信号量
sem_order = sem_open(SEM_ORDER,O_CREAT,SEM_FLAGS,0);
a_full = sem_open(A_FULL,O_CREAT,SEM_FLAGS,0);
b_full = sem_open(B_FULL,O_CREAT,SEM_FLAGS,0);
a_empty = sem_open(A_EMPTY,O_CREAT,SEM_FLAGS,1);
b_empty = sem_open(B_EMPTY,O_CREAT,SEM_FLAGS,1);
//开始创建共享内存
shm_id = shmget((key_t)SHM_KEY, (size_t)SHM_SIZE, SHM_FLAGS); //创建共享内存
shm_id_b = shmget((key_t)SHM_KEY_B, (size_t)SHM_SIZE, SHM_FLAGS); //创建共享内存
child= fork();
if(child==0){
//子进程。消费者,从shm_struct中读取字符,将其变成大写并输出到输出文件。
shm_struct * shm,*shm_b;
//映射共享内存
shm =(shm_struct*) shmat(shm_id, 0, 0);
shm_b = (shm_struct*) shmat(shm_id_b,0,0);
printf("\nChild memory attached at %X\n", (int)shm);
//打开输出文件
FILE * fp = fopen(OUT_PUT_FILE,"w");
//等待第一次写入
sem_wait(sem_order);
int turn = A_TURN;
while (shm->size | shm_b->size){ //两个缓冲区都没有字符则结束
if(turn == A_TURN){ //往A区写入
sem_wait(a_full);
my_tolower(shm->buf,SHM_BUF_SIZE);
fputs(shm->buf,fp);
memset(shm,'\0',SHM_BUF_SIZE);
shm->size = 0; //每次读取完都把size重置
turn = B_TURN; //A区写满了,换B
sem_post(a_empty);
}else{ //往B区写入
sem_wait(b_full);
my_tolower(shm_b->buf,SHM_BUF_SIZE);
fputs(shm_b->buf,fp);
memset(shm_b,'\0',SHM_BUF_SIZE);
shm_b->size = 0;
turn = A_TURN; //B区写满了,换A
sem_post(b_empty);
}
}
} else{
//父进程。生产者。从输入文件读取字符并将其依次写入到共享内存。
char* buffer =(char *) malloc(sizeof(char) * BUFF_SIZE + 1);
shm_struct * shm,*shm_b;
//打开需要处理的文件
FILE *fp = fopen(F_NAME,"r");
//映射共享内存
shm = (shm_struct *)shmat(shm_id, 0, 0);
shm_b = (shm_struct *)shmat(shm_id_b, 0, 0);
printf("\nParent memory attached at %X\n", (int)shm);
int turn = A_TURN,i=0;
while (!feof(fp)) { //只要文件没有读完,一直读
if (turn == A_TURN) {
sem_wait(a_empty); //往A区写
while ((shm->size + BUFF_SIZE < SHM_BUF_SIZE) && !feof(fp)) {
fgets(buffer, BUFF_SIZE, fp);
my_strncpy(shm, buffer, BUFF_SIZE);
}
turn = B_TURN; //A区写满了,换B
if (i == 0) {
sem_post(sem_order);
i = 1;
}
sem_post(a_full);
} else { //往B区写入
sem_wait(b_empty);
while ((shm_b->size + BUFF_SIZE < SHM_BUF_SIZE) && !feof(fp)) {
fgets(buffer, BUFF_SIZE, fp);
my_strncpy(shm_b, buffer, BUFF_SIZE);
}
turn = A_TURN; //B区写满了,换A
sem_post(b_full);
}
}
wait(NULL); //等待子进程结束
//删除共享内存
shmctl(shm_id,0,IPC_RMID);
shmctl(shm_id_b,0,IPC_RMID);
//删除信号量
sem_unlink(SEM_ORDER);
sem_unlink(A_EMPTY);
sem_unlink(A_FULL);
sem_unlink(B_EMPTY);
sem_unlink(B_FULL);
}
return 0;
}
int my_strncpy(shm_struct * dest,char* source,int size) {
int count = 0;
while ((count < size) && (source[count]) && source[count] != EOF)
++count;
strncpy(dest->buf + dest->size, source, count);
dest->size += count;
if(!source[count]){
dest->buf[dest->size]='\0';
dest->buf[dest->size+1]='\0';
}
return count;
}
int my_tolower(char *str,int len){
int i = 0;
for (; i < len && str[i] != EOF ; ++i) {
if(str[i] >= 'a' && str[i] <= 'z') {
str[i] += 'A' - 'a';
}
}
return i;
}
linux作业1
最新推荐文章于 2022-05-02 18:50:10 发布