posix_spawn 계열 함수
int posix_spawn(pid_t *restrict pid, const char *restrict path, const posix_spawn_file_actions_t *file_actions, const posix_spawnattr_t *restrict attrp, char *const argv[restrict], char *const envp[restrict]);
int posix_spawnp(pid_t *restrict pid, const char *restrict file, cosnt posix_spawn_file_actions_t *file_actions, const posix_spawnattr_t *restrict attrp, char *const argv[restrict], char *const envp[restrict]);
-
앞서 언급했듯이
fork-exec
는 부모 프로세스의 자원을 선택적으로 복제할 수 없으므로, 성능상의 문제와 추가적인 코딩이 복잡해지는 문제가 있었다. -
따라서,
posix_spawn
계열에서는 부모 프로세스의 자원을 선택적으로 복제하거나, 다룰 수 있는 통합 인터페이스가 제안되었는데 이를 가능하게 하는 것이 바로file_actions
,attrp
인수이다. -
만약
file_actions
,attrp
인수 부분에NULL
을 지정하면,fork-exec
와 동일한 작동, 즉 부모 프로세스의 자원을 모두 복제한다. -
posix_spawn
도 기본적으로는 부모 프로세스가 열었던 파일은 모두 상속 받는다. 만약 추가로 열어야하는 파일이 있거나, 기존에 열은 파일을 닫아야 할 필요가 있는 경우에는file_actions
매개변수를 이용한다.
posix_spawn_file_actions_t 구조체 조작
int posix_spawn_file_actions_init(posix_spawn_file_actions_t *file_actions);
int posix_spawn_file_destroy(posix_spawn_file_actions_t *file_actions);
int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *restrict file_actions, int fildes, const char *restrict path, int oflag, mode_t mode);
int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *file_actions, int fildes);
int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *file_actions, int fildes, int newfildes);
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <spawn.h>
#include <fcntl.h>
#include <string.h>
int main() {
int ret_err = 0;
pid_t pid_child;
char buf_err[64];
posix_spawn_file_actions_t posix_faction; /* file action struct */
char *argv_child[] = { "forkexec_child", NULL };
printf("Parent[%d]: Start\n", getpid());
if((ret_err = posix_spawn_file_actions_init(&posix_faction)) != 0) { /* init */
strerror_r(ret_err, buf_err, sizeof(buf_err));
fprintf(stderr, "Fail: file_actions_init :%s\n", buf_err);
exit(EXIT_FAILURE);
}
if ((ret_err = posix_spawn_file_actions_addopen(&posix_faction, 3,
"pspawn.log", O_WRONLY | O_CREAT | O_APPEND, 0664 )) != 0) {
strerror_r(ret_err, buf_err, sizeof(buf_err));
fprintf(stderr, "Fail: file_actions_addopen: %s\n", buf_err);
exit(EXIT_FAILURE);
}
ret_err = posix_spawn(&pid_child,
argv_child[0],
&posix_faction,
NULL,
argv_child,
NULL);
if ((ret_err = posix_spawn_file_actions_destroy(&posix_faction)) != 0) {
strerror_r(ret_err, buf_err, sizeof(buf_err));
fprintf(stderr, "Fail: file_actions_destory: %s\n", buf_err);
exit(EXIT_FAILURE);
}
printf("Parent[%d]: Wait for child(%d)\n", getpid(), (int)pid_child);
(void)wait(NULL);
printf("Parent[%d]: Exit\n", getpid());
return 0;
}
- 메모리를 해제하는 부분을 유의해서 보자, 예제에서는 한번 실행되고 곧바로 종료되기 때문에, 해제하지 않아도 메모리 누수를 신경 쓸 필요가 없지만, 연속적으로 실행되는 실무 프로그램에서는 민감한 문제이므로, 꼭 메모리 해제에 신경을 써야 한다.
posix_spawnattr_t 구조체 조작
int posix_spawnattr_init(posix_spawnattr_t *attr);
int posix_spawnattr_destroy(posix_spawnattr_t *attr);
int posix_spawnattr_getflags(const posix_spawnattr_t *restrict attr, short *restrict flags);
int posix_spawnattr_setflags(posix_spawnattr_t *attr, short flags);
-
posix_spawnattr_t
구조체는posix_spawnattr_init()
로 초기화를 한 뒤에 사용해야만 한다. -
그리고 사용이 끝난 구조체는
posix_spawnattr_destroy()
로 메모리를 해제해야 누수가 발생하지 않는다. -
따라서 메모리를 해제한 후에, 다시 사용할 필요가 있다면, 다시
posix_spawnattr_init()
로 초기화를 한 후에 사용하도록 한다. -
posix_spawnattr_t
에는EUID
, 프로세스 그룹, 기본 시그널 작동, 시그널 블록 마스크, 스케줄링 파라미터, 스케줄러를 설정할 수 있다. -
이중에서
EUID
설정을 제외한 나머지 기능들은 해당 속성의on/off
를 의미하는 플래그를 설정하고 개별적으로 속성을 등록하는 함수를 사용해야한다.