시스템 프로그래밍 6주차에는 프로세스 정보에 관하여 배운다.
- 프로세스란?
일단 프로그램과 프로세스의 차이에 대하여 먼저 알아보자.
프로그램은 실행 할 프로그램 과 데이터를 합친 컴퓨터 시스템에 실행 요청 전의 상태이다.
프로세스는 실행을 위해 커널에 등록된 작업을 말한다.
메모리 안에서 프로세스는

이렇게 차지하게 된다.
이제 리눅스 시스템에서 현재 실행중인 process 정보를 확인해보자.
윈도우의 작업관리자라고 생각하면 될 것이다.
ps를 사용하면 현재 실행중인 process 정보를 확인 할 수 있다.
옵션을 추가하자면 -j를 추가하면 job control format으로 출력이 가능하다.

top을 이용하면 현재 시스템 내 process 정보를 실시간 확인 가능하다.

사실 이 명령어가 ps 보다 더 작업관리자에 가깝다.
kill -signal pid 를 이용하면 해당 process에 signal을 전달한다.
이 부분은 나중에 더 자세히 배워보도록 하자.
- 프로세스 계층
Process ID
Process에 부여된 식별 번호로 시스템 내 유일한 번호가 할당이 된다.
Parent process
자신을 생성한 프로세스이며, 모든 프로세스는 부모 프로세스가 있다.
최상위 process = kernel (pid = 0)
Parent process의 ID를 PPID라고 한다.
Getting PID/PPID
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
pid_t getppid(void);
parameter는 없고 Process ID와 Parent process ID를 반환한다.
바로 예제 코드를 작성해보자
#include <unistd.h>
#include <stdio.h>
int main(void){
printf("PID : %d\n", (int)getpid());
printf("PPID : %d\n", (int)getppid());
return 0;
}
그냥 단순히 ID들을 가져오며 실행을 해보면

Process group
관련 process들을 묶은 것을 process group이라고 한다.
하나의 job 수행을 목적으로 하며, Process group에 전달 된 signal은 그룹 내 모든 프로세스에게 전달 된다.
그리고 그 중 가장 중심이 되는 Process를 Process group leader라고 한다.
Process Group의 ID는 leader의 PID를 따라간다.
Process group을 확인해보자.
우선 shell script를 작성한다.
echo test.sh ... start
ping 192.168.0.1
echo test.sh ... end
실행을 하고 터미널을 하나 더 열어서 Process ID들을 확인해본다.

이 화면이 Shell Script를 실행한 화면이고

ps -j e 명령어를 사용한 화면이다.
PGID가 같은 것들이 있는 것을 확인 할 수 있다.
kill -[signal num] -[groupID]로 해당 그룹 전체에 신호를 보낼 수 있다.
이 부분은 다음 시간에...
Setting process group ID
#include <unistd.h>
int setpgid(pid_t pid, pit_t pgid);
-pid
옮기고 싶은 target process의 pid
-pgid
설정하려는 group의 pgid
pid를 0으로 주면 current process로 설정하고, pgid = 0이면 pgid를 pid로 설정한다.
근데 여기서, 아무 group으로 이동할 수는 없고 같은 session 내에서만 이동이 가능하다.
session은 사용자가 로그인해 작업하고 있는 터미널 단위로 프로세스 그룹을 묶은 것을 말한다.
session은 하나의 foreground process group과 0개 이상의 background process group을 가진다.
foreground process group은 사용자의 입력을 받는 process group이고
background process group은 foreground process group 외의 process group을 말한다.
session에도 leader가 있는데 login shell process이다.
- Process 실행 시간
Process running time = system running time + user running time 이며
직관적으로 알 수 있겠지만
System running time은 System call에 소요된 시간
User running time은 사용자 모드에서 수행한 시간으로 사용자 작성 코드를 실행하는데 걸린 시간이다.
Getting process running time
#include <sys/times.h>
clock_t times(struct tms *buf);
-buf
running time 정보를 저장할 tms 구조체의 포인터이다.
return: 특정 시점부터 경과한 시간, -1(error)
parameter로 들어가는 tms 구조체는
struct tms {
clock_t tms_utime; /* [XSI] User CPU time */
clock_t tms_stime; /* [XSI] System CPU time */
clock_t tms_cutime; /* [XSI] Terminated children user CPU time */
clock_t tms_cstime; /* [XSI] Terminated children System CPU time */
};
이렇게 구성이 되어 있다.
바로 코드를 작성해보자.
#include <sys/types.h>
#include <sys/times.h>
#include <time.h>
#include <limits.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main(void){
time_t t;
struct tms mytms;
clock_t t1, t2;
if((t1 = times(&mytms)) == -1) {perror("times 1"); exit(1);}
sleep(5);
for(int i = 0; i < 999999; i++) time(&t);
if((t2 = times(&mytms)) == -1) {perror("times 2"); exit(1);}
printf("Read time : %.1f sec\n", (double)(t2 - t1) / sysconf(_SC_CLK_TCK));
printf("User time : %.1f sec\n", (double)mytms.tms_utime / sysconf(_SC_CLK_TCK));
printf("System time : %.1f sec\n", (double)mytms.tms_stime / sysconf(_SC_CLK_TCK));
return 0;
}
이렇게 실행시간을 측정해보면

User time과 System time까지 구할 수 있다.
- 환경변수
환경 변수는 Process 실행환경에 정의되어 있는 변수를 말한다.
우선 shell 환경에서 먼저 보자면
env를 사용해서 환경변수 목록을 확인할 수 있다.
$export 를 사용해서 환경변수를 선언할 수 있다. ($export 환경변수명 = 값)

Getting enviroment variables
프로그램을 만들 때에도 환경 변수를 가져올 수 있다.
environ 전역 변수 사용
#include <stdlib.h>
#include <stdio.h>
extern char **environ;
int main(void){
char **env;
env = environ;
while(*env){
printf("%s\n", *env);
env++;
}
return 0;
}

main의 인자로 전달
#include <stdio.h>
int main(int argc, char **argv, char **envp){
char **env;
env = envp;
while(*env){
printf("%s\n", *env);
env++;
}
return 0;
}

#include <stdlib.h>
char *getenv(const char *name);
-name
읽어올 환경변수 명
return: 환경변수 값, NULL(error)
이렇게 원하는 환경변수만을 가져올 수 있다.
#include <stdio.h>
#include <stdlib.h>
int main(void){
char *val;
val = getenv("MY_NAME");
if(val == NULL) printf("MY_NAME not defined\n");
else printf("MY_NAME = %s\n", val);
return 0;
}

Setting enviroment variables
#include <stdlib.h>
int putenv(char *string);
int setenv(const char *name, const char *value, int overwrite);
-string
추가할 환경변수와 값 (변수=값)
-name
추가할 환경변수의 이름
-value
추가할 환경변수의 값
-overwrite
추가되는 인수
Process에 의해 추가되는 환경 변수는 자신과 자식 프로세스에서만 유효하다.
#include <stdlib.h>
#include <stdio.h>
int main(void){
char *val;
val = getenv("MY_NAME");
if (val == NULL) printf("SHELL not defined\n");
else printf("1. MY_NAME = %s\n", val);
putenv("MY_NAME=SK");
val = getenv("MY_NAME");
printf("2. MY_NAME = %s\n", val);
return 0;
}
이렇게 MY_NAME에 해당하는 환경변수를 변경해도

그 process에서만 유효하다.
Unsetting enviroment variables
#include <stdlib.h>
int unsetenv(const char *name);
-name
삭제할 환경변수
return: 0(success), -1(error)
직관적으로 알 수 있듯 환경변수를 삭제하는 system call이다.
'학교 생활 > 시스템 프로그래밍' 카테고리의 다른 글
시스템 프로그래밍 5주차 (0) | 2023.03.05 |
---|---|
시스템 프로그래밍 4주차 (0) | 2023.03.02 |
시스템 프로그래밍 3주차 (0) | 2023.01.16 |
시스템 프로그래밍 2주차 (2) | 2023.01.15 |
시스템 프로그래밍 1주차 (0) | 2023.01.14 |