310 likes | 324 Views
Programming with Processes. [Slides from Prof. Yangsae Moon]. Process Identifiers (1/2). Every process has a unique process ID, a nonnegative integer. ( 모든 프로세스는 양수의 유일한 식별자 (PID) 를 가짐 ) Process ID 0: swapper scheduler process (it controls time slots for processes) system process
E N D
Programming with Processes [Slides from Prof. Yangsae Moon]
Process Identifiers (1/2) • Every process has a unique process ID, a nonnegative integer.(모든 프로세스는 양수의 유일한 식별자(PID)를 가짐) • Process ID 0: swapper • scheduler process (it controls time slots for processes) • system process • part of the kernel • no program on disk corresponds to this process
Process Identifiers (2/2) • Process ID 1: init process • invoked by the kernel at the end of the bootstrap procedure • /etc/init or /sbin/init • reads the system-dependent initialization files (/etc/rc*) • brings the system to a certain state (multi-user) • a normal user process but runs with super-user privileges • PID 1 is immortal • Process ID 2: pagedaemon • supports the paging of the virtual memory system • kernel process
PID 관련 함수 #include <sys/types.h> #include <unistd.h> pid_t getpid(void); // returns process ID pid_t getppid(void); // returns parent process ID uid_t getuid(void); // returns real user ID uid_t geteuid(void); // returns effective user ID gid_t getgid(void); // returns real group ID gid_t getegid(void); // returns effective group ID • None of these functions has an error return.
fork() (1/3) #include <sys/types.h> #include <unistd.h> pid_t fork(void); • fork() is the ONLY way to create a process in Unix kernel. • Child process is the new process created by fork(). • fork() is called once, but returns twice! • returns 0 in child process. • returns the child process ID in parent process.
fork() (2/3) • Child gets a copy of parent’s data space, heap, and stack • Often, read-only text segment is shared • Parent and child continue executing instructionsfollowing the fork() call • Often, fork() is followed by exec().
예제: fork.c (2/2) 실행 결과
Properties Inherited to the Child • real user and group ID, effective user and group ID • supplementary group IDs • process group ID, session ID • set-user-ID and set-group ID flags • current working directory • root directory • file mode creation mask • signal mask and dispositions • the close-on-exec flag for any open file descriptors • environment • attached shared memory segments • resource limits
Properties NOT Inherited to the Child • the return value from fork() • the process IDs are different • file locks • pending alarms are cleared for the child • the set of pending signals for the child is set to the empty set
exit() – Process Termination • A process can terminate in 5 ways: • Normal Termination • return from main() • exit() w/ cleanup procedure • _exit() w/o cleanup procedure • Abnormal Termination • calling abort() (generates SIGABRT signal) • process receives signals
wait(), waitpid() • Child terminates • Kernel sends SIGCHLD signal to parent. • an asynchronous event • Default action for signal: ignore it. • Signal handlers can be defined by users • call wait() to fetch the termination status of child. • (무사히, 죽을 수 있도록 배려~)
Race Conditions (1/2) • Multiple processes share some data. • Outcome depends on the order of their execution (i.e. RACE) • (Process A) x = 20; • (Process B) x += 10; • After fork(), we cannot predict if the parent or the child runs first! • The order of execution depends on: • System Load • Kernel’s Scheduling Algorithm
Race Conditions (2/2) • For parent to wait for child, • Call wait(), waitpid(), wait3(), wait4() • Use signals or other IPC methods • For child to wait for parent, • while(getppid() != 1) sleep(1); // Parent가 죽을 때까지 기다림 • Use signals or other IPC methods
예제: race.c (1/2) #include <stdio.h> // race.c #include <sys/types.h> err_sys(char *p) { perror(p); exit(-1); } int main(void) { pid_t pid; if ((pid = fork()) < 0) err_sys("fork error"); else if (pid == 0) charatatime("output from child\n"); else charatatime("output from parent\n"); exit(0); } charatatime(char *str) { char *ptr; int c; for (ptr = str; c = *ptr++; ) { putc(c, stdout); fflush(stdout); usleep(1); } }
예제: race.c (2/2) • 실행 결과
How to Avoid Race Condition? #include <stdio.h> #include <sys/types.h> int main(void) { pid_t pid; TELL_WAIT(); if ((pid = fork()) < 0) err_sys("fork error"); else if (pid == 0) { WAIT_PARENT(); // parent goes first charatatime("output from child\n"); } else { charatatime("output from parent\n"); TELL_CHILD(pid); } exit(0); } • How to implement TELL_WAIT(), WAIT_PARENT(), and TELL_CHILD()? • Use signals (강의노트 15) • Use IPC methods (강의노트 16)
Program Execution: exec() (1/2) • When a process calls one of the exec() functions • that process is completely replaced by the new program (새로운 프로그램으로 대체)(text, data, heap, and stack segments) • and the new program starts at its main function • 함수 exec()를 호출하여 완전히 다른 프로그램으로 실행된다.
exec() Functions #include <unistd.h> int execl(const char *pathname, const char *arg0, … , (char *)0); int execv(const char *pathname, const char *argv[]); int execle(const char *pathname, const char *arg0, … /* (char*) 0, char *const envp[] */); int execve(const char *pathname, const char *argv[],char *const envp[]); int execlp(const char *filename, const char *arg0, … , (char *)0); int execvp(const char *filename, const char *argv[]); All six return: -1 on error, no return on success • exec? (p, l, v, e) • p: filename (not pathname) • l: takes a list of arguments (the last argument should be a null pointer) • v: takes argv[] vector • e: takes envp[] array without ‘e’, the environment variables of the calling process are copied
Properties inherited to the new program • same ID • process ID, parent process ID, real user ID, real group ID, supplementary group IDs, process group ID, session ID • controlling terminal • time left until alarm clock • current working directory • root directory • file mode creation mask • file locks • process signal mask • pending signals • resource limits, …
예제: nexec.c, echoall.c (4/4) • 실행 결과
system() #include <stdlib.h> int system(const char *cmdstring); • 주어진 스트링(cmdstring)을 Shell 상에서 수행시킨다. • e.g.) system(“date > file”); • system() is implemented by calling fork, exec, and waitpid. • Return values: • -1 with errno: fork or waitpid fails • 127: exec fails • Termination status of shell: all 3 functions succeed
예제: myls.c (1/2) #include <stdio.h> // myls.c main(int ac, char *av[]) { int i; char cmdstr[1024]; strcpy(cmdstr, "/bin/ls "); for(i=1;i < ac;i++) { strcat(cmdstr, av[i]); strcat(cmdstr, " "); } fprintf(stdout, "cmdstr = \"%s\"\n", cmdstr); system(cmdstr); exit(0); }
예제: myls.c (2/2) • 실행 결과
Process Times – skip #include <sys/times.h> clock_t times(struct tms *buf); Returns: elapsed wall clock time in clock ticks if OK, -1 on error struct tms ( clock_t tms_utime; /* user cpu time */ clock_t tms_stime; /* system cpu time */ clock_t tms_cutime; /* child user cpu time */ clock_t tms_cstime; /* child system cpu time */ } • Wall clock time: the amount of time the process takes to run and depends on the system loads. (실제 수행된 시간) • User CPU time: attributed to user instructions(사용자 코드에 의해 CPU를 점유한 시간) • System CPU time: attributed to the kernel, when it executes on behalf of the process (시스템 코드에 의해 CPU를 점유한 시간)