9. 프로세스 제어
9.1 프로세스 생성
1. 프로세스 생성
- fork() 시스템 호출
- 부모 프로세스를 똑같이 복제하여 새로운 자식 프로세스를 생성(자기복제)
- 부모 프로세스를 똑같이 복제하여 새로운 자식 프로세스를 생성(자기복제)
ex) fork1.c
#include <stdio.h>
#include <unistd.h>
/* 자식 프로세스를 생성한다. */
int main()
{
int pid;
printf("[%d] 프로세스 시작 \n", getpid());
pid = fork();
printf("[%d] 프로세스 : 리턴값 %d\n", getpid(), pid);
}
[31563] 프로세스 시작
[31563] 프로세스 : 리턴값 31564
[31564] 프로세스 : 리턴값 0
2. 부모 프로세스와 자식 프로세스 구분
- fork() 호출 후에 리턴값이 다르므로 이 리턴값을 이용해 부모프로세스와 자식프로세스를 구별하고 서로 다른 일을 하도록 할 수 있다.
pid = fork();
if(pid==0)
{ 자식프로세스의 실행코드 }
else
{ 부모프로세스의 실행코드 }
ex) fork2.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
/* 부모 프로세스가 자식 프로세스를 생성하고 서로 다른 메시지를 프린트 */
int main()
{
int pid;
pid = fork();
if(pid==0)
{
printf("[CHILD] : HELLO~ pid = %d\n",getpid());
}
else
{
printf("[PARENT] : HELLO~ pid= %d\n",getpid());
}
}
ex) fork3.c
#include <stdlib.h>
#include <stdio.h>
/* 부모 프로세스가 두 개의 자식 프로세스를 생성한다. */
int main()
{
int pid1, pid2;
pid1 = fork();
if (pid1 == 0) {
printf("[Child 1] : Hello, world ! pid=%d\n", getpid());
exit(0);
}
pid2 = fork();
if (pid2 == 0) {
printf("[Child 2] : Hello, world ! pid=%d\n", getpid());
exit(0);
}
}
3. 프로세스 기다리기 : wait()
- 자식 프로세스 중의 하나가 끝날 때까지 기다린다.
- 끝난 자식 프로세스의 종료 코드가 status에 저장되며,- 끝난 자식 프로세스의 번호를 리턴
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
int main()
{
int pid, child, status;
printf("[%d] 부모 프로세스 시작 \n", getpid());
pid = fork();
if (pid == 0) {
printf("[%d] 자식 프로세스 시작 \n", getpid( ));
exit(1);
}
child = wait(&status); // 자식 프로세스가 끝나기를 기다린다.
printf("[%d] 자식 프로세스 %d 종료 \n", getpid(), child);
printf("\t종료 코드 %d\n", status>>8);
}
[23184] 부모 프로세스 시작
[23185] 자식 프로세스 시작
[23184] 자식 프로세스 23185 종료
종료 코드 1
4. fork() 후에 파일 공유
- 자식은 부모의 fd 테이블을 복사한다.
- 부모와 자식이 같은 파일 디스크립터를 공유- 같은 파일 오프셋을 공유
- 부모와 자식으로부터 출력이 서로 섞이게됨
- 자식에게 상속되지 않는 성질
- fork()의 반환값
- 프로세스 ID
- 파일 잠금
- 설정된 알람과 시그널
9.2 프로그램 실행
프로그램 실행
-
fork() 이후 자식프로세스는 부모 프로세스와 똑같은 코드 실행
-
자식 프로세스에세 새 프로그램 실행
: __exec() 시스템 호출 사용
: 프로세스 내의 프로그램을 새 프로그램으로 대치
-
보통 fork() 후에 exec()
프로그램 실행 : exec()
- 프로세스가 exec() 호출
: 그 프로새스 내의 프로그램은 완전히 새로운 프로그램으로 대치 ( 자기대치 )
: 새 프로그램의 main()부터 실행이 시작된다.
fork() 이후 자식프로세스는 부모 프로세스와 똑같은 코드 실행
자식 프로세스에세 새 프로그램 실행
: __exec() 시스템 호출 사용
: 프로세스 내의 프로그램을 새 프로그램으로 대치
보통 fork() 후에 exec()
: 그 프로새스 내의 프로그램은 완전히 새로운 프로그램으로 대치 ( 자기대치 )
: 새 프로그램의 main()부터 실행이 시작된다.
- exec() 호출이 성공하면 리턴할 곳이 없어진다.
- 성공한 exec() 호출은 절대 리턴하지 않는다
- 보통 fork() 후에 exec()를 호출하는데
: 새로 실행할 프로그램에 대한 정보를 arguments로 전달한다.
- exec() 호출이 성공하면
자식 프로세스는 새로운 프로그램을 실행하게 되고 부모는 계속해서 다음 코드를 실행하게 된다.t
if ((pid = fork()) == 0 ){
exec( arguments );
exit(1);
}
// 부모 계속 실행
ex) execute1.c
#include <stdio.h>
/* 자식 프로세스를 생성하여 echo 명령어를 실행한다. */
int main( )
{
printf("부모 프로세스 시작\n");
// 자식프로세스 생성
if (fork( ) == 0) {
execl("/bin/echo", "echo", "hello", NULL);
fprintf(stderr,"첫 번째 실패");
exit(1);
}
printf("부모 프로세스 끝\n");
ex2) execute2.c
#include <stdio.h>
#include <stdlib.h>
/* 자식프로세스를 생성하여 echo 명령어를 실행한다. */
int main()
{
printf("부모 프로세스 시작\n");
if(fork()==0)
{
execl("/bin/echo","echo","hello",NULL);
fprintf(stderr,"첫 번째 실패");
exit(1);
}
if(fork()==0)
{
execl("/bin/date","date",NULL);
fprintf(stderr,"두 번째 실패");
exit(2);
}
if (fork( ) == 0)
{
execl("/bin/ls","ls", "-l", NULL);
fprintf(stderr,"세 번째 실패");
exit(3);
}
printf("부모 프로세스 끝\n");
}
ex) execute3.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>
/* 자식프로세스를 생성하여 echo 명령어를 실행한다. */
int main(int argc, char* argv[])
{
int child,pid,status;
pid = fork();
// 자식프로세스
if(pid==0)
{
execv(argv[1],&argv[1]);
fprintf(stderr,"%s:실행 불가\n",argv[1]);
}
// 부모 프로세스
else
{
child = wait(&status);
printf("[%d] 자식 프로세스 %d 종료\n",getpid(),pid);
printf("\t종료 코드 %d\n",status>>8);
}
}
system()
-
자식프로세스를 생성하고 /bin/sh로 지정된 명령어를 실행시킨다
ex) system("date > file); -
system() 함수 구현
: fork(), exec(), waitpid() 시스템 호출이용 -
반환값
명령어의 종료코드 : 성공
127 : exec() 실패
-1 : 다른오류 -
system() 구현
#include <sys/types.h> /* system.c */
#include <sys/wait.h>
#include <errno.h>
#include <unistd.h>
int system(const char *cmdstring)
{
pid_t pid; int status;
if (cmdstring == NULL) /* 명령어가 NULL인 경우 */
return(1);
if ( (pid = fork()) < 0)
{
status = -1; /* /* 프로세스 생성 실패 */
}
else if (pid == 0)
{ /* 자식 */
execl("/bin/sh", "sh", "-c", cmdstring, (char *) 0);
_exit(127); /* execl 실패 */
}
else
{ /* 부모 */
while (waitpid(pid, &status, 0) < 0)
if (errno != EINTR) {
status = -1; /* waitpid()로부터 EINTR외의 오류 */
break;
}
}
return(status);
}
Author And Source
이 문제에 관하여(9. 프로세스 제어), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@kdo6301/9.-프로세스-제어저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)