0

我先说这是一项家庭作业,我在编写 SIGCHLD 处理程序时遇到了困难。我需要访问子进程中的变量。

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>


#define TEXT_LEN 10
#define NUM_RESCUE_PLOWS 4
#define NUM_VICTIMS_TO_RESCUE 40


/*  PURPOSE:  To keep trap of the number of victims that have been rescued.
 */
int numRescuedVictims = 0;



/*  PURPOSE:  To keep track of the process id's of the rescuing snow plows.
 */
pid_t plowPid[NUM_RESCUE_PLOWS];


/*  PURPOSE:  To note that at least one child plow has finished.  Reports the
 *process id and the number of victims rescued for each child plow.
 *'sigNum' tells the signal number.  No return value
 */
//  You may want to define a SIGCHLD listener here
//  It should have a loop that wait()s for children and
//  and prints how many victims each has rescued.
void listenSIGCHLD(int sig)
{
  int status;
  pid_t pidWait;
  while((pidWait = wait(&status)) > 0)
    printf("Plow %d rescued %d victim(s)", plowId, numVictimsRescued);
}


/*  PURPOSE:  To handle being informed of a rescued victim.  'sigNum' tells
 *signal number.  No return value.
 */
//  You may want to define a SIGUSR1 listener here
//  It increments 'numRescuedVictims' and prints the total number rescued victims
void listenSIGUSR1(int sig)
{
  numRescuedVictims += &numVictimsRescued;
  printf("We've rescued %d victims!" numRescuedVictims);
}


/*  PURPOSE:  To make 'NUM_RESCUE_PLOWS' processes to run 'rescuingPlow' to
 *rescue stuck victims, and then tell them to quit after all
 *'NUM_VICTIMS_TO_RESCUE' victims have been rescued.  Ignores parameters.
 *Returns 'EXIT_SUCCESS' to OS.
 */
int main ()
{

  //  I.  Applicability validity check:


  //  II.  Rescue victims:

  //  II.A.  Install 'SIGUSR1' handler:
  signal(SIGUSR1, listenSIGUSR1);

  // Install 'SIGUSR1' handler
  //  Install your SIGCHLD handler here
  signal(SIGCHLD, listenSIGCHLD);

  //  II.B.  Tell NUM_RESCUE_PLOWS plows to start rescuing the victims:

  int i;
  int myPid= getpid();

  for  (i = 0;  i < NUM_RESCUE_PLOWS;  i++)
    {
      //  Do a fork() and save it in plowPid[i]
      plowPid[i] = fork();
      //  If plowPid[i] is less than 0 then do:
      if(plowPid[i] < 0)
    {
      fprintf(stderr,"Dude, your system is WAY to busy to play rescuer!\n");
      return(EXIT_FAILURE);
    }

      //  If plowPid[i] is equal to 0 then do:
      else if(plowPid[i] == 0)
    {
      char pidText[TEXT_LEN];
      char indexText[TEXT_LEN];
    }
      snprintf(pidText,TEXT_LEN,"%d",myPid);
      snprintf(indexText,TEXT_LEN,"%d",i);
      execl("./rescuingPlow","rescuingPlow",pidText,indexText,NULL);
      fprintf(stderr,"Dude, somebody stole my plow!!\n");
      return(EXIT_FAILURE);
    }


  //  II.C.  Wait until all victims have been rescued:

  while  (numRescuedVictims < NUM_VICTIMS_TO_RESCUE)
    {
      sleep(1);
      printf("Searching for victims . . .\n");
    }


  //  III.  Finished:

  //  Loop to send SIGTERM to all NUM_RESCUE_PLOWS plow processes
  for (int i = 0; i < NUM_RESCUE_PLOWS; i++)
    {
      kill(plowPid[i], SIGTERM);
    }
  int toSleep= NUM_RESCUE_PLOWS;

  //  sleep() can be interrupted by SIGCHLD.  Whenever it is interrupted
  //  it returns the number of seconds that still remain on its alarm
  //  clock.  Let's wait until it has slept its full amount incase it
  //  was prematured interrupted by SIGCHLD.
  do
    {
      toSleep= sleep(toSleep);
    }
  while  (toSleep > 0);

  printf("Ready for the NEXT snow storm!\n");
  return(EXIT_SUCCESS);
}

`

这就是最终生成的进程。虽然我还没有解决这个问题。

/*
 *  rescuingPlow.c
 *
 *  Compile with $ gcc rescuingPlow.c -o rescuingPlow
 */
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>


/*  PURPOSE:  To keep track of the number of victims that this process
 *  rescued.
 */
int numVictimsRescued   = 0;



/*  PURPOSE:  To return the number of victims rescued to the OS.  'sigNum'
 *  tells the signal number.  No return value.
 */
//  You may want to write a SIGTERM handling function
//  that returns to the OS 'numVictimsRescued'.



/*  PURPOSE:  To rescue victims at random intervals and inform parent process
 *  by sending it SIGUSR1 until receiving SIGTERM.  First parameter (after
 *  program name) tells parent's process id.  Second parameter tells this
 *  plow's index.
 */
int main    (int argc, char* argv[])
{

  //  I.  Applicability validity check:

  pid_t parentPID;
  int   plowId;

  if  (argc < 3)
  {
    fprintf(stderr,"USAGE: rescuingPlow <parentPID> <plowId>\n");
    return(EXIT_FAILURE);
  }

  parentPID = atoi(argv[1]);
  plowId    = atoi(argv[2]);


  //  II.  Rescuing victims until told to stop:

  //  II.A.  Install signal handler:

  //  Install your SIGTERM handler here
  srand(plowId);  //  Uniquely initialize random number generator so they act independently of each other


  //  II.B.  Rescue victims:

  //  Write an endless loop that:
  //  (1) Does 'sleep((rand() % 6) + 1);'
  //  (2) Increments 'numVictimsRescued'
  //  (3) Does 'printf("Plow %d rescued %d victim(s)!\n",plowId,numVictimsRescued);'
  //  (4) Send 'SIGUSR1' to 'parentPID'


  //  III.  Finished:

  return(EXIT_SUCCESS);
}

我不完全确定我要去哪里或如何处理那个。我非常有信心我可以处理存在的大多数其他问题。

4

2 回答 2

1

如果不使用某些 IPC 机制,子进程只能将 8 位的值传递给父进程。

通过将宏应用于成功调用 or返回的值,子进程将这 8 位作为参数发送到调用exit()并由父进程接收。请参阅和了解详情。WEXITSTATUS()statuswait()waitpid()man 2 exitman 2 wait

如果我没记错的话,标准定义的最小值是 8 位。一些实现可能允许更多位。

更新:

如何使用示例wait()

int child_exit_code = -1;
int status = -1;
pid_t pid = wait(&status);
if (-1 != pid)
  child_exit_code = WEXITSTATUS(status);
于 2013-05-06T06:08:25.293 回答
0

You can use shmget to allocate shared memory.

Use it before forking, and then the allocated memory will be accessible to both child and parent.
The child can store whatever it wants there, and the parent will read it.

于 2013-05-06T07:09:54.590 回答