DELMAR_ 2023-03-16 23:26 采纳率: 57.1%
浏览 108
已结题

C语言多个进程操作共享内存中的队列

我想实现一个程序:多进程操作共享内存中的队列。先放上我的代码
以下是我的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;

      }
    
}

  • 写回答

8条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2023-03-18 02:17
    关注
    不知道你这个问题是否已经解决, 如果还没有解决的话:

    如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^
    评论

报告相同问题?

问题事件

  • 系统已结题 3月24日
  • 修改了问题 3月17日
  • 创建了问题 3月16日

悬赏问题

  • ¥15 做个有关计算的小程序
  • ¥15 MPI读取tif文件无法正常给各进程分配路径
  • ¥15 如何用MATLAB实现以下三个公式(有相互嵌套)
  • ¥30 关于#算法#的问题:运用EViews第九版本进行一系列计量经济学的时间数列数据回归分析预测问题 求各位帮我解答一下
  • ¥15 setInterval 页面闪烁,怎么解决
  • ¥15 如何让企业微信机器人实现消息汇总整合
  • ¥50 关于#ui#的问题:做yolov8的ui界面出现的问题
  • ¥15 如何用Python爬取各高校教师公开的教育和工作经历
  • ¥15 TLE9879QXA40 电机驱动
  • ¥20 对于工程问题的非线性数学模型进行线性化