리눅스 시스템 네트워크 프로그래밍 (1) - 프로세스 (1)

이동욱

2021/07/03

Categories: 시스템 프로그래밍 Tags: 시스템 프로그래밍

프로세스


확장된 프로세스 실행 방법


fork()


0 -> 자식 프로세스에게 리턴되는 값
양수 -> 부모 프로세스에게 리턴되며, 자식 프로세스의 PID를 의미한다.
-1 -> 에러, 복제 실패
switch (ret = fork()) {
  case 0:
    do_child(); /* 자식 프로세스인 경우에 실행될 코드 */
    break;
  case -1: /* 에러가 난 경우 */
    do_errorcatc();
    break;
  default: /* 양수는 부모 프로세스이며 ret에 자식 프로세스의 PID가 저장됨 */
    do_parent();
    break;
}
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>

int main() {
  int i = 0;
  pid_t ret;

  for (i = 0; i < 3; i++) {
    ret = fork();
    printf("[%d] PID(%d) PPID(%d)\n", i, getpid(), getppid());
#ifndef OMIT_SWITCH
    switch (ret) {
      case 0:
        pause();
        return 0;
      case -1:
        break;
      default:
        break;
    }
#endif
  }
  wait(NULL);
  return 0;
}
gcc -DOMIT_SWITCH _Wall -o fork_omit_swich fork_process.c 

result

exec(3) 계열 함수


int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ..., char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);

execl 계열을 사용한 예

execl("/bin/ls", "ls", "-al", NULL);
execlp("ls", "ls", "-al", NULL);

execv 계열을 사용한 예

char *argv_exec[] = {"ls", "-al", NULL};
execv("/bin/ls", argv_exec);

char *argv_exec[] = {"ls", "-al", NULL};
execvp("ls", argv_exec);
#include <stdio.h>
#include <unistd.h>

int main() {
  if (execl("/bin/ls", "ls", "-al", NULL) == -1) {
    perror("excel");
  }
  printf("+ arfter execl\n");
  return 0;
}

상속되지 않는 파일 기술자


forkexec_parent.c*

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

int main() {
  pid_t pid_child;
  printf("Parent[%d]: Start\n", getpid());
  int fd = open("forkexec.log", O_WRONLY | O_CREAT | O_APPEND, 0644);

  if (fd == -1) {
    perror("FAIL: open");
    exit(EXIT_FAILURE);
  }

  dprintf(fd, "Parent[%d]: Open log file(fd=%d)\n", getpid(), fd);

#ifdef APPLY_FD_CLOEXEC
  int ret_fcntl;
  if ((ret_fcntl = fcntl(fd, F_SETFD, FD_CLOEXEC)) == -1) {
    perror("FAIL: fcntl(F_SETFD, FD_CLOEXEC)");
    exit(EXIT_FAILURE);
  }
#endif

  /* fork-exec code */
  char *argv_exec[] = {"fork_exec_child", (char*) NULL};

  switch ((pid_child = fork())) {
    case 0: /* child process */
      execv(argv_exec[0], argv_exec);
      break;
    case -1: /* error */
      perror("FAIL: FORK");
      break;
    default: /* parent process */
      wait(NULL);
      break;
  }
  printf("Parent[%d]: Exit\n", getpid());
  return 0;
}

forkexec_child.c

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

int main() {
  dprintf(STDOUT_FILENO, "Child[%d]: Start\n", getpid());
  dprintf(3, "Child[%d]: fd(3): Test fd.\n", getpid());
  close(3);
  dprintf(STDOUT_FILENO, "Child[%d]: Exit\n", getpid());
  return 0;
}
Parent[5935]: Open log file(fd=3)
Child[5936]: fd(3): Test fd.
gcc -DAPPLY_FD_CLOEXEC -o forkexec_parent_fdcloexec forkexec_parent.c
Parent[6014]: Open log file(fd=3)

system 함수


참고 문헌

>> Home