8. 프로세스

김동웅·2021년 10월 4일
0

UNIX

목록 보기
9/14

핵심 개념

프로세스는 실행중인 프로그램이다.
은 사용자와 운영체제 사이에 창구 역할을 하는 소프트웨어로 사용자로부터 명령어를 입력받아 이를 처리하는 명령어 처리기 역할을 한다.
• 프로그램이 실행되면 프로그램의 시작 루틴에게 명령줄 인수와 환경 변수가 전달된다.
• exit()는 뒷정리를 한 후 프로세스를 정상적으로 종료시키고 _exit()는 뒷정리를 하지 않고 프로세스를 즉시 종료시킨다.
• exit 처리기는 exit()에 의한 프로세스 종료 과정에서 자동으로 수행된다.
각 프로세스는 프로세스 ID를 갖는다. 각 프로세스는 자신을 생성해준 부모 프로세스가 있다.
• 각 프로세스는 실제 사용자 ID유효 사용자 ID를 가지며 실제 그룹 ID와 유효 그룹 ID를 갖는다.
• 프로세스 이미지는 텍스트(코드), 데이터, 힙, 스택 등으로 구성된다.


- 8.1 쉘과 프로세스

⭕ 1. 쉘이란?

  • 쉘은 사용자와 운영체제 사이에서 창구 역할을 하는 소프트웨어
  • 쉽게 말해서 명령어 처리기
  • 사용자로부터 명령어를 입력받아 이를 처리한다.

2. 복합 명령어

명령어 열

$ 명령어1; … ; 명령어n
$ date; who; pwd

명령어 그룹

$ (명령어1; … ; 명령어n)
$ date; who; pwd > out1.txt
> date와 who가 출력되고 pwd가 out1.txt에 저장됨

$ (date; who; pwd) > out2.txt
> date와 who와 pwd 가 out2.txt에 저장됨

3. 전면처리 vs 후면처리

  • 전면처리 : 명령어 입력 -> 명령어가 전면에서 실행되며 명령어 실행이 끝날때까지 쉘이 기다려준다.

  • 후면처리 : 명령어들을 후면에서 처리하고 전면에서는 다른작업을 할 수 있다.
    동시에 여러작업을 수행할수 있다.
    -> $ 명령어 &

    후면처리 예시 :

  • $ (sleep 100; echo done) &
    -> [1] 8320 // 작업번호

  • $ find . -name test.c -print &
    -> [2] 2934 // 작업번호

  • $jobs // 현재작업리스트 출력
    ->
    [1] + Running ( sleep 100; echo done )
    [2] - Running find . -name test.c –print

  • $ fg %작업번호
    -> 작업번호의 명령어 출력

4. ⭕ 프로세스란?(process)

실행중인 프로그램을 프로세스 라고 부른다.

각 프로세스는 유일한 프로세스 번호 PID를 갖는다.

ps 명령어를 사용하여 나의 프로세스들을 볼 수 있다.

+ sleep 명령어

• 지정된 시간만큼 실행을 중지한다.
$ sleep 초
$ (echo 시작; sleep 5; echo 끝)

kill 명령어

$ kill [프로세스번호] -> 해당 프로세스 강제종료

wait 명령어

$ wait [프로세스번호]

  • 해당 프로세스 번호를 갖는 자식 프로세스가 종료될 때까지 기다린다.
  • 프로세스 번호를 지정하지 않으면 모든 자식 프로세스를 기다린다.
$ (sleep 10; echo 1번 끝) &

$ (sleep 10; echo 2번 끝) &

$ echo 3번 끝; wait; echo 4번 끝

3번 끝
1번 끝
2번 끝
4번 끝

exit 명령어

  • 쉘을 종료하고 종료코드(exit code)을 부모 프로세스에 전달
    $ exit [종료코드]

- 8.2 프로그램 시작

1. 프로그램 실행 시작

  • exec 시스템 호출
  1. C 시작 루틴에 명령줄 인수와 환경변수를 전달하고
  2. 프로그램을 실행시킨다.
  • C 시작 루틴(Start-up routine)
    : main 함수를 호출하면서 명령줄 인수, 환경 변수를 전달
exit( main( argc, argv ) );

: 실행이 끝나면 반환값을 받아 exit 한다.

2. 명령줄 인수/ 환경 변수

int main(int argc, char * argv[]);

// argc : 명령줄 인수의 개수
// argv[] : 명령줄 인수 리스트를 나타내는 포인터 배열

ex) args.c


#include <stdio.h>
/* 모든 명령줄 인수를 출력한다. */

int main(int argc, char *argv[])
{

int i;
  for (i = 0; i < argc; i++) /* 모든 명령줄 인수 출력 */
	   printf("argv[%d]: %s \n", i, argv[i]);
exit(0);
}

ex) environ.c

#include <stdio.h>
/* 모든 환경 변수를 출력한다. */
int main(int argc, char *argv[])
{
char **ptr;
extern char **environ;
for (ptr = environ; *ptr != 0; ptr++) /* 모든 환경 변수 값 출력*/
printf("%s \n", *ptr);
exit(0);
}

3. 환경 변수 접근

  • __getenv() 시스템 호출을 사용하여 환경 변수를 하나씩 접근가능
#include <stdlib.h>

char *getenv(const char *name);

// 환경변수 name의 값을 반환한다. 해당 변수가 없으면 NULL 반환

ex) printenv.c

#include <stdio.h>
#include <stdlib.h>

/* 환경 변수를 3개 프린트한다. */
int main(int argc, char *argv[])
{
char *ptr;
ptr = getenv("HOME");
printf("HOME = %s \n", ptr);

ptr = getenv("SHELL");
printf("SHELL = %s \n", ptr);

ptr = getenv("PATH");
printf("PATH = %s \n", ptr);

exit(0);
}

HOME = /home/kdo6301 
SHELL = /bin/bash 
PATH = /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin 

4. 환경 변수 설정

  • putenv(), setenv()를 사용하여 특정 환경 변수를 설정


- 8.3 프로그램 종료

1. 프로그램 종료

  • 정상 종료
    - main() 실행을 마치고 리턴하면 C 시작 루틴은 이 리턴값을 가지고 exit()을 호출
    - 프로그램 내에서 직접 exit()을 호출
    - 프로그램 내에서 직접 _exit()을 호출
exit()모든 열려진 스트림을 닫고(fclose), 출력 버퍼의 내용을 디스크에 쓰는(fflush 버퍼비우기) 등 뒷정리후 프로세스를 정상적으로 종료
_exit() 뒷정리를 하지않고 프로세스를 즉시 종료
  • 비정상 종료 (시그널에 의한 종료)
    - abort()
    : 프로세스에 SIGABRT 시그널을 보내 프로세스를 비정상적으로 종료

2. atexit()

#include <stdlib.h>

void atexit(void (*func)(void));
  • exit 처리기를 등록함 / 프로세스당 32개까지

  • func
    - exit 처리기

    • 함수포인터(이름)
  • exit()는 exit handler 들을 등록된 역순으로 호출

ex) exit 처리기 예 (atexit.c)

#include <stdio.h>
#include <stdlib.h>

static void exit_handler1(void), exit_handler2(void);

int main(void)
{
	if(atexit(exit_handler1)!=0)
		perror("Can't regist exit_handler1 ! ");

	if(atexit(exit_handler2)!=0)
		perror("Can't regist exit_handler2 ! ");

	printf("main end\n");
	exit(0);
}

static void exit_handler1()
{
	printf("첫 번째 exit 처리기\n");
}

static void exit_handler2()
{
	printf("두 번째 exit 처리기\n");
}
main end
두 번째 exit 처리기
첫 번째 exit 처리기

8.4 프로세스 ID

1. 프로세스 ID

  • 각 프로세스는 프로세스를 구별하는 번호인 프로세스 ID를 갖는다.
  • 각 프로세스는 자신을 생성해준 부모 프로세스가 있다.

ex) pid.c // 프로세스 번호출력


#include <stdio.h>
#include <unistd.h>

int main()
{

	int pid;
	printf("my process num is %d \n",getpid());
	printf("my parent process is %d \n",getppid());
}

2. 프로세스의 사용자 ID

  • 프로세스는 프로세스 ID 외에 프로세스의 사용자 ID와 그룹 ID를 갖는다.

⬛ 프로세스의 실제 사용자 ID

  • 그 프로세스를 실행한 원래 사용자의 사용자 ID로 설정됨

ex)
chang이라는 사용자 ID로 로그인하여 어떤 프로그램 실행 ->
그 프로세스의 실제 사용자 ID는 chang이 됨.

⬛ 프로세스의 유효 사용자 ID

  • 현재 유효한 사용자 ID로 새로 파일을 만들 때나 파일에 대한 접근 권한을 검사할 때 주로 사용된다.

  • 보통 유효 사용자ID와 실제 사용자 ID는 특별한 실행파일 을 실행할때 제외하고 동일.

+ 프로세스 ID 반환 함수

ex) uid.c

#include <stdio.h>
#include <pwd.h>
#include <grp.h>
#include <unistd.h>

int main()
{
	int pid;
	printf("나의 실제 사용자 ID : %d(%s) \n", getuid(), getpwuid(getuid())->pw_name);
	printf("나의 유효 사용자 ID : %d(%s) \n", geteuid(), getpwuid(geteuid())->pw_name);
	printf("나의 실제 그룹 ID : %d(%s) \n", getgid(), getgrgid(getgid())->gr_name);
	printf("나의 유효 그룹 ID : %d(%s) \n", getegid(), getgrgid(getegid())->gr_name);

	return 0;
}

나의 실제 사용자 ID : 1000(kdo6301)
나의 유효 사용자 ID : 1000(kdo6301)
나의 실제 그룹 ID : 1000(kdo6301)
나의 유효 그룹 ID : 1000(kdo6301)

+ 프로세스 ID 변경 함수

3. set-user-id 실행파일

  • 특별한 실행권한 set-user-id
    - set-user-id 설정된 실행파일을 실행하면
    - 이 프로세스의 유효 사용자 ID는 그 실행파일의 소유자로 바뀜.

    • 이 프로세스는 실행되는 동안 그 파일의 소유자 권한을 갖게 됨.

      example) /usr/bin/passwd 명령어

    • set-user-id 실행권한이 설정된 실행파일이며 소유자는 root

    • 일반 사용자가 이 파일을 실행하게 되면 이 프로세스의 유효한 사용자 ID는 root가 됨.

    • etc/passwd 처럼 root만 수정할 수 있는 파일의 접근 및 수정이 가능

  • set-user-id 설정
    : set-user-id 실행권한은 심볼릭모드 's'로 표시

    $ ls –asl /bin/su /usr/bin/passwd

    32 -rwsr-xr-x. 1 root root 32396 2011-05-31 01:50 /bin/su
    28 -rwsr-xr-x. 1 root root 27000 2010-08-22 12:00 /usr/bin/passwd

    : $ chmod 4755 file
    -> file의 실행권한을 set-user-id로 변경

    ex)

    • $ cp uid uid2
    • $ sudo chown root uid2
    • $ sudo chmod 4755 uid2
    • $ ./uid2

5. 프로세스 구조

  • 프로세스는 실행중인 프로그램이다.

  • 프로그램 실행을 위해서는 프로그램의 코드, 데이터, 스택, 힙, U-영역 등이 필요하다.

  • 프로세스 이미지는 메모리 내의 프로세스 레이아웃

  • 프로그램 자체가 프로세스는 아니다.


0개의 댓글

관련 채용 정보