Путеводитель по Руководству Linux

  User  |  Syst  |  Libr  |  Device  |  Files  |  Other  |  Admin  |  Head  |



   posix_spawnp    ( 3 )

порождать процесс (spawn a process)

  Name  |  Synopsis  |  Description  |  Return value  |  Error  |  Versions  |  Conforming to  |  Note  |  Bugs  |    Examples    |  See also  |

Примеры (Examples)

The program below demonstrates the use of various functions in
       the POSIX spawn API.  The program accepts command-line attributes
       that can be used to create file actions and attributes objects.
       The remaining command-line arguments are used as the executable
       name and command-line arguments of the program that is executed
       in the child.

In the first run, the date(1) command is executed in the child, and the posix_spawn() call employs no file actions or attributes objects.

$ ./a.out date PID of child: 7634 Tue Feb 1 19:47:50 CEST 2011 Child status: exited, status=0

In the next run, the -c command-line option is used to create a file actions object that closes standard output in the child. Consequently, date(1) fails when trying to perform output and exits with a status of 1.

$ ./a.out -c date PID of child: 7636 date: write error: Bad file descriptor Child status: exited, status=1

In the next run, the -s command-line option is used to create an attributes object that specifies that all (blockable) signals in the child should be blocked. Consequently, trying to kill child with the default signal sent by kill(1) (i.e., SIGTERM) fails, because that signal is blocked. Therefore, to kill the child, SIGKILL is necessary (SIGKILL can't be blocked).

$ ./a.out -s sleep 60 & [1] 7637 $ PID of child: 7638

$ kill 7638 $ kill -KILL 7638 $ Child status: killed by signal 9 [1]+ Done ./a.out -s sleep 60

When we try to execute a nonexistent command in the child, the exec(3) fails and the child exits with a status of 127.

$ ./a.out xxxxx PID of child: 10190 Child status: exited, status=127

Program source

#include <spawn.h> #include <stdint.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <wait.h> #include <errno.h>

#define errExit(msg) do { perror(msg); \ exit(EXIT_FAILURE); } while (0)

#define errExitEN(en, msg) \ do { errno = en; perror(msg); \ exit(EXIT_FAILURE); } while (0)

char **environ;

int main(int argc, char *argv[]) { pid_t child_pid; int s, opt, status; sigset_t mask; posix_spawnattr_t attr; posix_spawnattr_t *attrp; posix_spawn_file_actions_t file_actions; posix_spawn_file_actions_t *file_actionsp;

/* Parse command-line options, which can be used to specify an attributes object and file actions object for the child. */

attrp = NULL; file_actionsp = NULL;

while ((opt = getopt(argc, argv, "sc")) != -1) { switch (opt) { case 'c': /* -c: close standard output in child */

/* Create a file actions object and add a "close" action to it. */

s = posix_spawn_file_actions_init(&file_actions); if (s != 0) errExitEN(s, "posix_spawn_file_actions_init");

s = posix_spawn_file_actions_addclose(&file_actions, STDOUT_FILENO); if (s != 0) errExitEN(s, "posix_spawn_file_actions_addclose");

file_actionsp = &file_actions; break;

case 's': /* -s: block all signals in child */

/* Create an attributes object and add a "set signal mask" action to it. */

s = posix_spawnattr_init(&attr); if (s != 0) errExitEN(s, "posix_spawnattr_init"); s = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGMASK); if (s != 0) errExitEN(s, "posix_spawnattr_setflags");

sigfillset(&mask); s = posix_spawnattr_setsigmask(&attr, &mask); if (s != 0) errExitEN(s, "posix_spawnattr_setsigmask");

attrp = &attr; break; } }

/* Spawn the child. The name of the program to execute and the command-line arguments are taken from the command-line arguments of this program. The environment of the program execed in the child is made the same as the parent's environment. */

s = posix_spawnp(&child_pid, argv[optind], file_actionsp, attrp, &argv[optind], environ); if (s != 0) errExitEN(s, "posix_spawn");

/* Destroy any objects that we created earlier. */

if (attrp != NULL) { s = posix_spawnattr_destroy(attrp); if (s != 0) errExitEN(s, "posix_spawnattr_destroy"); }

if (file_actionsp != NULL) { s = posix_spawn_file_actions_destroy(file_actionsp); if (s != 0) errExitEN(s, "posix_spawn_file_actions_destroy"); }

printf("PID of child: %jd\n", (intmax_t) child_pid);

/* Monitor status of the child until it terminates. */

do { s = waitpid(child_pid, &status, WUNTRACED | WCONTINUED); if (s == -1) errExit("waitpid");

printf("Child status: "); if (WIFEXITED(status)) { printf("exited, status=%d\n", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { printf("killed by signal %d\n", WTERMSIG(status)); } else if (WIFSTOPPED(status)) { printf("stopped by signal %d\n", WSTOPSIG(status)); } else if (WIFCONTINUED(status)) { printf("continued\n"); } } while (!WIFEXITED(status) && !WIFSIGNALED(status));

exit(EXIT_SUCCESS); }