我想实现一个程序:多进程操作共享内存中的队列。先放上我的代码
以下是我的file.h文件,其中含有队列操作的基本函数申明
#ifndef _QUEUE_
#define _QUEUE_
typedef struct team{
char name[20];
int noteWin;
int noteLost;
struct team* next;
}*Team;
typedef struct queue{
Team head;
Team tail;
}*Queue;
Queue allocQueue();
Queue initQueue(Queue queue);
Team allocTeam();
Team initTeam(Team team, char* name);
char* getName(Team team);
int getNoteWin(Team team);
int getNoteLost(Team team);
Team getHead(Queue queue);
Team getTail(Queue queue);
Team getNext(Team team);
int isEmpty(Queue queue);
Queue enQueue(Queue queue, Team team);
Queue deQueue(Queue queue);
int getSize(Queue queue);
void traverse(Queue queue);
#endif
然后如下是我的file.h头文件的具体实现file.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "file.h"
Queue allocQueue(){
Queue queue = (Queue)malloc(sizeof(struct queue));
return queue;
}
Queue initQueue(Queue queue){
queue->head = queue->tail = NULL;
return queue;
}
Team allocTeam(){
Team team = (Team)malloc(sizeof(struct team));
return team;
}
Team initTeam(Team team, char* name){
team->noteWin = 0;
team->noteLost = 0;
strcpy(team->name, name);
team->next = NULL;
return team;
}
int getNoteWin(Team team){
return team->noteWin;
}
int getNoteLost(Team team){
return team->noteLost;
}
char* getName(Team team){
return team->name;
}
Team getHead(Queue queue){
return queue->head;
}
Team getTail(Queue queue){
return queue->tail;
}
Team getNext(Team team){
return team->next;
}
int isEmpty(Queue queue){
return getHead(queue) == NULL;
}
int isNULL(Team team){
return team==NULL;
}
Queue enQueue(Queue queue, Team team){
if (isEmpty(queue)) {
queue->head = queue->tail = team;
}
else {
queue->tail->next = team;
queue->tail = team;
}
return queue;
}
Queue deQueue(Queue queue){
if (isEmpty(queue)) {
return NULL; // File vide
}
else {
Team team = getHead(queue);
queue->head = getNext(team);
if (isNULL(getHead(queue))) {
queue->tail = NULL;
}
free(team);
return queue;
}
}
int getSize(Queue queue){
Team team = getHead(queue);
int size = 0;
while(!isNULL(team)){
++size;
team = getNext(team);
}
return size;
}
void traverse(Queue queue){
Team team = getHead(queue);
while(!isNULL(team)){
printf("%s -> ", getName(team));
team = getNext(team);
}
}
// TEST
// int main(){
// Queue q = allocQueue();
// q = initQueue(q);
// Team team1 = allocTeam();
// team1 = initTeam(team1, "bonjour");
// q = enQueue(q, team1);
// Team team2 = allocTeam();
// team2 = initTeam(team2, "hello");
// q = enQueue(q, team2);
// Team team3 = allocTeam();
// team3 = initTeam(team3, "nihao");
// q = enQueue(q, team3);
// Team team4 = allocTeam();
// team4 = initTeam(team4, "sawadika");
// q = enQueue(q, team4);
// printf("size = %d\n",getSize(q));
// traverse(q);
// q = deQueue(q);
// printf("size = %d\n",getSize(q));
// traverse(q);
// }
然后再是关于共享内存以及信号量的实现文件cTools.h和cTools.c
#ifndef _CTOOLS_
#define _CTOOLS_
#include <sys/types.h>
#include <sys/ipc.h>
#include "file.h"
#include <sys/shm.h>
#include <sys/sem.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#define MAXMSGSIZE 1024
// 共享内存的建立和释放
Queue shmalloc(key_t key, int size);
int shmfree(key_t key);
// semaphore的建立和释放
int semalloc(key_t key, int valInit);
int semfree(int semid);
// 信号量的处理
void P(int semid); // block
void V(int semid); // unblock
// 读取比赛队伍名字
void recupererNomEquipe(int size, char (*arr)[16], char filePath[30]);
#endif
#include "cTools.h"
Queue shmalloc(key_t key, int size) {
Queue queue;
int owner = 0;
int shmid = shmget(key, size, 0600);
if (shmid == -1) {
owner = 1;
shmid = shmget(key,size,IPC_CREAT|IPC_EXCL|0600);
}
if (shmid == -1) return 0;
queue = (Queue)shmat(shmid, 0, 0);
if (queue == (Queue)-1) {
if (owner) shmctl(shmid, IPC_RMID, 0);
return 0;
}
return queue;
}
int shmfree(key_t key){
int shmid = shmget(key, 0, 0644);
return shmctl(shmid, IPC_RMID, 0);
}
int semalloc(key_t key, int valInit) {
int semid = semget(key,1,0);
if (semid == -1){
semid = semget(key,1,IPC_CREAT|IPC_EXCL|0600);
if (semid == -1)
return -1;
if (semctl(semid,0,SETVAL,valInit) == -1) {
/* il faut detruire le semaphore */
semctl(semid,0,IPC_RMID,0);
return -1;
}
}
return semid;
}
int semfree(int semid) {
return semctl(semid,0,IPC_RMID,0);
}
static struct sembuf sP = {0,-1,0};
static struct sembuf sV = {0,1,0};
void P(int semid){
semop(semid,&sP,1);
}
void V(int semid) {
semop(semid,&sV,1);
}
void recupererNomEquipe(int size, char (*arr)[16], char filePath[30]){
FILE *f = fopen(filePath,"r");
int i,j;
for(i = 0; i < size; i++){
fscanf(f, "#%[^#]#\n", arr[i]);
}
fclose(f);
}
然后我的问题来了,我目前在做一个测试,我想首先实现两个进程对一个共享内存的操作,就像下面代码中,首先向队列中填入两个element,再用子进程实现deQueue出队操作。我原本是想实现这一步后,再拓展到更多线程,但是我在这一步就卡住了。子进程能够实现deQueue操作,同时这一步操作也能与父进程同步,但是为什么子进程中“team4”,加不进去啊?我根本不能不能理解。为什么deQueue都能执行,team4的enQueue操作不行了?
#include "cTools.h"
#include <pthread.h>
int main(int argc, char *argv[])
{
char filePath[30];
int size;
if(argc == 3){
size = atoi(argv[1]);
strcpy(filePath,argv[2]);
}
char nbE[size][16];
recupererNomEquipe(size,nbE,filePath);
int shmKey = ftok(".", 0);
Queue queue = shmalloc(shmKey,sizeof(Queue));
// queue = allocQueue();
queue = initQueue(queue);
Team team = allocTeam();
team = initTeam(team,"bonjour");
queue = enQueue(queue, team);
Team team2 = allocTeam();
team2 = initTeam(team2,"hello");
queue = enQueue(queue, team2);
Team team3 = allocTeam();
team3 = initTeam(team3,"nihao");
queue = enQueue(queue, team3);
// pthread_mutex_t mutex;
// pthread_mutex_init(&mutex, NULL);
key_t semKey = ftok(".",0);
int semid = semalloc(semKey, 1);
pid_t pid;
switch(pid = fork()){
case -1:
perror("fork");
return -1;
case 0:
P(semid);
deQueue(queue);
Team team4 = allocTeam();
team4 = initTeam(team4,"goodbye");
queue = enQueue(queue, team4);
traverse(queue);
printf("\n");
V(semid);
shmfree(shmKey);
exit(EXIT_SUCCESS);
default:
P(semid);
Team team5 = allocTeam();
team5 = initTeam(team5,"auRevoir");
queue = enQueue(queue, team5);
traverse(queue);
printf("\n");
V(semid);
wait(NULL);
printf("\n\n\n");
traverse(queue);
semfree(semid);
shmfree(shmKey);
return 0;
}
}