msgrcv()函数在子进程中失败

时间:2016-10-16 21:05:53

标签: c message message-queue message-passing msgrcv

我目前正在尝试在主进程及其子进程之间发送消息。我正在使用消息传递来强制执行一个关键部分,但我在子进程中的消息接收功能失败了,我不知道是否有不同的方式我应该发送消息。我的消息接收功能是在父进程中获取消息,因此我无法调试用户进程未收到的原因。

oss.c

#include "sharedmem.h"

pid_t pid;

//Shared memory and Message queue variables
key_t key;
int shm_ID;

key_t ossMessageKey;
int ossMessage_ID;

key_t userMessageKey;
int userMessage_ID;

//Clock declaration
clockStruct *OssClock = NULL;

//Max number of proccesses to spawn
const int maxProcesses = 100;

int process_count = 1;
char *processNum;
int totalProcesses = 0;
int nextUser = 1;

volatile sig_atomic_t killFlag = 0;

struct msqid_ds tmpbuf;

void ReceivedKill(int signum);
void sendMsg(int msgQueID, int msgType);
void getMsg(int msgQueID, int msgType, FILE *fp);

int main(int argc, char *argv[])
{
  //Processes and general variables
  int c;
  int i;
  int status;
  int sVal = 5;
  int tVal = 20;
  char *logfile = "test.out";
  char *user_sVal;
  char *user_tVal;
  char *user_shmid;

  FILE *fp;

  //Memory allocation
  user_sVal = malloc(sizeof(int));
  user_tVal = malloc(sizeof(int));
  user_shmid = malloc(sizeof(int));
  processNum = malloc(sizeof(int));

  signal(SIGALRM, ReceivedKill);
  signal(SIGINT, ReceivedKill);

  //Command line arguments
  while((c = getopt(argc, argv, "hs:l:t:")) != -1)
  {
    switch (c)
    {
      case 'h':
        printf("Options:\n");
        printf("[-s]: Change max number of slaves spawned\n");
        printf("[-l]: Change name of log file\n");
        printf("[-t]: Change number of seconds until Master will terminate itself and all children\n");
        exit(0);
        break;
      case 's':
        sVal = atoi(optarg);
        break;
      case 'l':
        logfile = optarg;
        break;
      case 't':
        tVal = atoi(optarg);
        break;
      case '?':
        if(optopt == 's')
        {
          exit(1);
        }
        else if(optopt == 'l')
        {
          exit(1);
        }
        else if(optopt == 't')
        {
          exit(1);
        }
        else
        {
          printf("Unknown option entered. Invoke [-h] to see a list of commands\n");
          exit(1);
        }
    }
  }

  sprintf(user_sVal, "%d", sVal);
  sprintf(user_tVal, "%d", tVal);


  alarm(tVal);

  //Setup shared memory

  //Make our keys
  if((key = ftok("./", 'x')) == -1)
  {
    perror("ftok failed");
    exit(1);
  }

  if((ossMessageKey = ftok("./", 'y')) == -1)
  {
    perror("ftok failed");
    exit(1);
  }

  if((userMessageKey = ftok("./", 'z')) == -1)
  {
    perror("ftok failed");
    exit(1);
  }

  //Allocate the memory
  if((shm_ID = shmget(key, sizeof(clockStruct*), IPC_CREAT | 0777)) == -1)
  {
    perror("shmget could not allocate");
    exit(1);
  }

  if((ossMessage_ID = msgget(ossMessageKey, IPC_CREAT | 0777)) == -1)
  {
    perror("msgget failed");
    exit(1);
  }

  if((userMessage_ID = msgget(userMessageKey, IPC_CREAT | 0777)) == -1)
  {
    perror("msgget failed");
    exit(1);
  }



  printf("Attaching memory\n");
  //Attach
  OssClock = (clockStruct *)shmat(shm_ID, 0, 0);
  OssClock->seconds = 0;
  OssClock->nanoseconds = 0;

  printf("Detaching memory\n");
  shmdt(OssClock);

  //printf("Values are: Sval: %d, Logfile: %s, Tval: %d, shm_ID: %d\n", sVal, logfile, tVal, shm_ID);

  printf("ossMessage_ID: %d, userMessage_ID: %d\n", ossMessage_ID, userMessage_ID);

  printf("Forking processes\n");

  sprintf(user_shmid, "%d", shm_ID);


  //Process forking
  for(i = 0; i < sVal; i++)
  {

    pid = fork();
    //totalProcesses++;
    process_count++;

    if(pid == -1)
    {
      perror("Failed to fork\n");
      exit(1);
    }

    if(pid == 0)
    {
      sprintf(processNum, "%d", process_count);
                              //arg1     arg2       arg3     arg4        arg5
      execl("./user", "user", user_sVal, user_tVal, logfile, user_shmid, processNum, (char *) 0);
      perror("Could not execute user process\n");
    }

    printf("Total Processes: %d\n", process_count);

  }

  //Master process
  if(pid > 0)
  {

    sendMsg(userMessage_ID, nextUser);

    while(totalProcesses < maxProcesses && killFlag != 1)
    {
      sleep(5);
      getMsg(ossMessage_ID, 3, fp);
      //wait(&status);
      //process_count--;
    }

    printf("Freeing memory\n");
    free(user_sVal);
    free(user_tVal);
    free(user_shmid);
  }

  //Deallocate shared memory
  printf("Clearing shared memory and message queues\n");
  if(shmctl(shm_ID, IPC_RMID, NULL) == -1)
  {
    fprintf(stderr, "Shared memory remove failed. Remove manually please\n");
    return -1;
  }

  if(msgctl(ossMessage_ID, IPC_RMID, NULL) == -1)
  {
    perror("msgctl");
    exit(1);
  }

  if(msgctl(userMessage_ID, IPC_RMID, NULL) == -1)
  {
    perror("msgctl");
    exit(1);
  }

  printf("Program done\n");

  return 0;
}

void ReceivedKill(int signum)
{
  signal(SIGQUIT, SIG_IGN);
  signal(SIGALRM, SIG_IGN);
  signal(SIGINT, SIG_IGN);

  sleep(1);
  if(signum == SIGINT)
  {
    killFlag = 1;
    fprintf(stderr, "\n**Received CTRL-C. Killing all children**\n\n");
  }
  else if(signum == SIGALRM)
  {
    killFlag = 1;
    fprintf(stderr, "\n**Timer ran out. Killing all child processes**\n\n");
  }

  kill(-getpgrp(), SIGQUIT);
  //Sends quit signal to entire slave group which will then use their signal handlers to kill themselves

}

void sendMsg(int msgQueID, int msgType)
{
  struct messageBuffer message;

  printf("Sending message\n");

  message.msgtype = msgType;

  sprintf(message.msgText, "Unblock\n");

  if(msgsnd(msgQueID, (void *) &message, sizeof(message.msgText), IPC_NOWAIT) == -1)
  {
    perror("Message send error\n");
  }

  printf("Message sent\n");

}

void getMsg(int msgQueID, int msgType, FILE *fp)
{
  msgctl(ossMessage_ID, IPC_STAT, &tmpbuf);
  struct messageBuffer message;

  if(msgrcv(msgQueID, (void *) &message, sizeof(message.msgText), msgType, MSG_NOERROR) == -1)
  {
    if(errno != ENOMSG)
    {
      perror("oss msgrc");
    }
    printf("No message to receive in OSS\n");
  }
  else
  {
    printf("Slave %d sent a message back: %s\n", tmpbuf.msg_lspid, message.msgText);
    totalProcesses++;

    sendMsg(userMessage_ID, ++nextUser);
  }


}

user.c的

#include "sharedmem.h"


void sigHandler(int signum);
void sendMsg(int queID, int msgType);
void getMsg(int queID, int msgType);
volatile sig_atomic_t killSig = 0;

clockStruct *OssClock;

pid_t userPID;

//Message queue keys and ID's
key_t ossMessageKey;
int ossMessage_ID;

key_t userMessageKey;
int userMessage_ID;

int pNum = 0;

int main(int argc, char *argv[])
{
  int sVal_num = atoi(argv[1]);
  int tVal_num = atoi(argv[2]);
  char *filename = argv[3];
  int shm_ID = atoi(argv[4]);
  pNum = atoi(argv[5]);
  int keychecker;
  key_t key;

  userPID = getpid();

  signal(SIGINT, SIG_IGN);
  signal(SIGQUIT, sigHandler);

  //printf("Sval: %d, tVal: %d, Filename: %s, shm_ID: %d, Process num: %d\n", sVal_num, tVal_num, filename, shm_ID, pNum);

  //Shared memory Setup
  if((key = ftok("./", 'x')) == -1)
  {
    perror("ftok for slave failed");
    exit(1);
  }

  keychecker = shmget(key, sizeof(clockStruct*), IPC_CREAT | 0777);
  if(keychecker != shm_ID)
  {
    perror("Keys do not match. Error passing key to slave?\n");
    exit(1);
  }

  //Message queues
  if((ossMessageKey = ftok("./", 'y')) == -1)
  {
    perror("ftok for slave failed");
    exit(1);
  }

  if((userMessageKey = ftok("./", 'z')) == -1)
  {
    perror("ftok for slave failed");
    exit(1);
  }

  if((ossMessage_ID = msgget(ossMessageKey, 0777)) == -1)
  {
    perror("msgget");
    exit(1);
  }

  if((userMessage_ID = msgget(userMessageKey, 0777)) == -1)
  {
    perror("msgget");
    exit(1);
  }

  //printf("ossMessage_ID: %d, userMessage_ID: %d\n", ossMessage_ID, userMessage_ID);


  //printf("Attaching shared memory\n");
  OssClock = (clockStruct*)shmat(shm_ID,0,0);

  //printf("Seconds: %d, Nanoseconds: %d\n", OssClock->seconds, OssClock->nanoseconds);


  //Enter critical section

  getMsg(userMessage_ID, pNum);
  printf("Slave %d is entering critical section\n", pNum);

  if(killSig != 1)
  {
    //printf("Accessing shared memory\n");
    sendMsg(ossMessage_ID, 3);
  }




  shmdt(OssClock);

  kill(userPID, SIGTERM);
  kill(userPID, SIGKILL);

  exit(0);
  return 0;


}

void sigHandler(int signum)
{
  killSig = 1;
}

void sendMsg(int queID, int msgType)
{
  struct messageBuffer message;

  message.msgtype = msgType;

  sprintf(message.msgText, "Slave %d got message\n", pNum);

  if(msgsnd(queID, (void *) &message, sizeof(message.msgText), IPC_NOWAIT) == -1)
  {
    perror("\nuser send error\n");
  }
}

void getMsg(int queID, int msgType)
{
  struct messageBuffer message;

  //printf("Got message from oss\n");

  if(msgrcv(queID, (void *) &message, sizeof(message.msgText), msgType, MSG_NOERROR | IPC_NOWAIT) == -1)
  {
    if(errno != ENOMSG)
    {
      perror("user msgrcv");
    }
    printf("User can't receive message\n");
  }
  else
  {
    printf("Got message from oss\n");
    printf("Message received by user %d: %s\n", pNum, message.msgText);
  }
}

sharedmem.h

#ifndef SHAREDMEM_H
#define SHAREDMEM_H

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <getopt.h>
#include <ctype.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/msg.h>

typedef struct clockStruct
{
  int seconds;
  int nanoseconds;
} clockStruct;


//For message queue. Template according to book
typedef struct messageBuffer
{
  long msgtype; //Type of message
  char msgText[100]; //Actual message to send. Size is length of message.
} messageBuffer;

#endif

1 个答案:

答案 0 :(得分:0)

我一周都在挣扎着同样的错误!

typedef struct messageQueue{
    char msgText[MSGTXTLEN];
    long int msgType;
    int pid;
    int data1;
    int data2;
    char opr;
    int result;
}msgQdata_s;

但修复了结构重新排序

typedef struct messageQueue{
    long int msgType;
    char msgText[MSGTXTLEN];
    int pid;
    int data1;
    int data2;
    char opr;
    int result;
}msgQdata_s;

并在发送之前指定值

msgQdata_s rc1Data_s;
rc1Data_s.msgType = 1; 

希望这会有所帮助!