сбой функции msgrcv() в дочернем процессе

#c #message #message-queue #message-passing #msgrcv

#c #Сообщение #очередь сообщений #передача сообщений #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 spawnedn");
        printf("[-l]: Change name of log filen");
        printf("[-t]: Change number of seconds until Master will terminate itself and all childrenn");
        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 commandsn");
          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 memoryn");
  //Attach
  OssClock = (clockStruct *)shmat(shm_ID, 0, 0);
  OssClock->seconds = 0;
  OssClock->nanoseconds = 0;

  printf("Detaching memoryn");
  shmdt(OssClock);

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

  printf("ossMessage_ID: %d, userMessage_ID: %dn", ossMessage_ID, userMessage_ID);

  printf("Forking processesn");

  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 forkn");
      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 processn");
    }

    printf("Total Processes: %dn", process_count);

  }

  //Master process
  if(pid > 0)
  {

    sendMsg(userMessage_ID, nextUser);

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

    printf("Freeing memoryn");
    free(user_sVal);
    free(user_tVal);
    free(user_shmid);
  }

  //Deallocate shared memory
  printf("Clearing shared memory and message queuesn");
  if(shmctl(shm_ID, IPC_RMID, NULL) == -1)
  {
    fprintf(stderr, "Shared memory remove failed. Remove manually pleasen");
    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 donen");

  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**nn");
  }
  else if(signum == SIGALRM)
  {
    killFlag = 1;
    fprintf(stderr, "n**Timer ran out. Killing all child processes**nn");
  }

  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 messagen");

  message.msgtype = msgType;

  sprintf(message.msgText, "Unblockn");

  if(msgsnd(msgQueID, (void *) amp;message, sizeof(message.msgText), IPC_NOWAIT) == -1)
  {
    perror("Message send errorn");
  }

  printf("Message sentn");

}

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

  if(msgrcv(msgQueID, (void *) amp;message, sizeof(message.msgText), msgType, MSG_NOERROR) == -1)
  {
    if(errno != ENOMSG)
    {
      perror("oss msgrc");
    }
    printf("No message to receive in OSSn");
  }
  else
  {
    printf("Slave %d sent a message back: %sn", 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: %dn", 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: %dn", ossMessage_ID, userMessage_ID);


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

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


  //Enter critical section

  getMsg(userMessage_ID, pNum);
  printf("Slave %d is entering critical sectionn", pNum);

  if(killSig != 1)
  {
    //printf("Accessing shared memoryn");
    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 messagen", pNum);

  if(msgsnd(queID, (void *) amp;message, sizeof(message.msgText), IPC_NOWAIT) == -1)
  {
    perror("nuser send errorn");
  }
}

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

  //printf("Got message from ossn");

  if(msgrcv(queID, (void *) amp;message, sizeof(message.msgText), msgType, MSG_NOERROR | IPC_NOWAIT) == -1)
  {
    if(errno != ENOMSG)
    {
      perror("user msgrcv");
    }
    printf("User can't receive messagen");
  }
  else
  {
    printf("Got message from ossn");
    printf("Message received by user %d: %sn", 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:

Я боролся с той же ошибкой в течение недели!

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

но исправлено, просто переупорядочивая структуру

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

и присвоите значение перед его отправкой

 msgQdata_s rc1Data_s;
rc1Data_s.msgType = 1; 
 

Надеюсь, это поможет!