Home > Mobile >  How can I pass a variable between a parent and child process in C?
How can I pass a variable between a parent and child process in C?

Time:03-06

My question is, how can I pass the X value between process, I don't wanna use a global variable for this.

int main(int argc, char *argv[])
{
    pid_t pid;
    int x;
    x = 1;
    pid=fork();
  // Daqui para baixo executa o fork
  if (pid == 0){ //Processo filho
    printf("Processo Filho\n");
    x = x   2;
    printf("Somando 2 ao X, temos: %d\n", x);

    exit(0);
    }
    
    else
    { //Processo pai
    printf("Processo pai\n");
    printf("O valor inicial de X é: %d\n", x);
    wait(NULL);
    x = x * 4;
    printf("Agora multiplicando o valor de X por 4 temos: %d\n", x);
    printf("Criança completa\n");
    }
  return 0;
}

I'm trying just to print the X value using the shmget, but I get -1, I'm currently just testing if I can pass the X value using that

int main(int argc, char *argv[])
{
    pid_t pid;
    int x;
    int shmid;
    int *shmptr;
    x = 1;
    shmid = shmget(x, 4*sizeof(int), IPC_CREAT | 0666);
    shmptr = (int *) shmat(shmid, NULL, 0);
    pid=fork();
  // Daqui para baixo executa o fork
  if (pid == 0){ //Processo filho
    printf("Processo Filho\n");
    printf("%d\n",shmid);
    x = x   2;
    printf("Somando 2 ao X, temos: %d\n", x);

    exit(0);
    }
    
    else
    { //Processo pai
    printf("Processo pai\n");
    printf("O valor inicial de X é: %d\n", x);
    wait(NULL);
    x = x * 4;
    printf("Agora multiplicando o valor de X por 4 temos: %d\n", x);
    printf("Criança completa\n");
    }
  return 0;
}

CodePudding user response:

When you fork, you are creating a process that is an exact copy of the current process. It also copies data so you have access to the exact same things you have on the main process except the pid (the return of the call to fork()).

So your x value is copied. If you change it in the child process it will not be changed in the parent process even if you are using global variables

int x = 0;
pid = fork();
if (pid == 0) // Child process
{
    printf("%d\n", x); // will print 0
    x  ;
}
else
{
    printf("%d\n", x); // Will print 0
}
printf("%d\n", x); // Will print 0 in the parent process and 1 in the child process

If you want to retrieve your X value from the child process you should look to the waitpid function.

Here is an example on how to use it:

int pid = fork();

if (pid == -1)
    exit(1);

if (pid == 0) // Child
{
    exit(42);
}

int wstatus;
if (waitpid(pid, &wstatus, 0) == -1)
    exit(1);
if (!WIFEXITED(wstatus))
    exit(1);

printf("process exit status: %d\n", WEXITSTATUS(wstatus)); // 42

CodePudding user response:

On POSIX systems it's also possible to use real-time signals to send up to 64 bits of data between processes. Per POSIX 7 2.4.2 Realtime Signal Generation and Delivery:

This section describes functionality to support realtime signal generation and delivery.

Some signal-generating functions, such as high-resolution timer expiration, asynchronous I/O completion, interprocess message arrival, and the sigqueue() function, support the specification of an application-defined value, either explicitly as a parameter to the function or in a sigevent structure parameter. The sigevent structure is defined in <signal.h> and contains at least the following members:

Member Type            Member Name             Description

int                    sigev_notify            Notification type.
int                    sigev_signo             Signal number.
union sigval           sigev_value             Signal value.
void(*)(union sigval)  sigev_notify_function   Notification function.
(pthread_attr_t*)      sigev_notify_attributes Notification attributes.

...

The sigval union is defined in <signal.h> and contains at least the following members:

Member Type            Member Name             Description

int                    sival_int               Integer signal value.
void*                  sival_ptr               Pointer signal value.

The sival_int member shall be used when the application-defined value is of type int; the sival_ptr member shall be used when the application-defined value is a pointer.

Sending the value is simple:

int value = ...;

union sigval sv;
memset( &sv, 0, sizeof( sv ) );
sv.sival_int = value;

int rc = sigqueue( pid, SIGRTMAX, sv );

On a system with 64-bit pointers, you can hack the use of the sival_ptr pointer field to send 64 bits of data:

uint64_t value = ...;

union sigval sv;
memset( &sv, 0, sizeof( sv ) );
sv.sival_ptr = ( void * )( uintptr_t ) value;

int rc = sigqueue( pid, SIGRTMAX, sv );

You can use a signal handler to retrieve the value:

void handler( int sig, siginfo_t *info, void *context )
{
    int value = info->si_value.sival_int;

    ...
}

...

struct sigaction sa;

memset( &sa, 0, sizeof( sa ) );

sa.sa_sigaction = handler;
sa.sa_flags = SA_RESTART | SA_SIGINFO;

sigaction( SIGCHLD, &sa, NULL );

Or, using sigwaitinfo():

sigset_t sigSet;
memset( &sigSet, 0, sizeof( sigSet ) );
sigemptyset( &sigSet );

sigaddset( &sigSet, SIGRTMAX );

sigprocmask( SIG_BLOCK, &sigSet, NULL );

siginfo_t siginfo;

int sigNum = sigwaitinfo( &sigSet, &siginfo, );
if ( SIGRTMAX == sigNum )
{
    int value = siginfo.si_value.sival_int;

    ...
}
  •  Tags:  
  • c
  • Related