Upload
rafe-holmes
View
217
Download
0
Embed Size (px)
Citation preview
제 11 장 프로세스 시스템 프로그래밍
1
Objectives
Process Start and Exit Create a child process Execute a new program within a process Signal System boot
2
© 숙대 창병모 3
프로세스 시작 /종료
© 숙대 창병모 4
Process Start
Kernel exec system call
C start-up routineuser process
int main(int argc, char * argv[]);
call return
© 숙대 창병모 5
main() int main(int argc, char *argv[]);
argc : the number of command-line arguments argv[] : an array of pointers to the arguments
C start-up routine Started by the kernel (by the exec system call) Take the command-line arguments and the
environment from the kernel Call main exit( main( argc, argv) );
© 숙대 창병모 6
Process Termination Normal termination
return from main() calling exit() : calling _exit()
Abnormal termination calling abort() terminated by a signal
© 숙대 창병모 7
exit()
프로세스를 정상적으로 종료한다
cleanup processing 을 수행한다 모든 열려진 스트림을 닫고 (fclose) 출력 버퍼의 내용을 디스크에 쓴다 (fflush)
status the exit status of a process 이 값은 UNIX shell 에 의해서 사용됨
#include <stdlib.h>
void exit(int status);
© 숙대 창병모 8
_exit()
프로세스를 정상적으로 종료한다
커널로 즉시 리턴한다
#include <unistd.h>
void _exit(int status);
© 숙대 창병모 9
atexit()
exit handler 를 등록한다 프로세스당 32 개까지
func an exit handler a function pointer
exit() 는 exit handler 들을 등록된 역순으로 호출한다
#include <stdlib.h>
void atexit(void (*func)(void)); returns: 0 if OK, nonzero on error
© 숙대 창병모 10
C Program Start and Termination
retu
rn ca
ll
exitfunction
userfunction
mainfunction
C start-uproutine
exit handler
exit handler
standard I/Ocleanup
kernel
user process
exit(does not return)exit
(does not return)
exit
(does not re
turn)
call
return
call
return
callreturn
……
_exit
exec
_exit
_exit
retu
rn ca
ll
© 숙대 창병모 11
/* doatexit.c */static void my_exit1(void), my_exit2(void);
int main(void) { if (atexit(my_exit2) != 0) perror("can't register my_exit2"); if (atexit(my_exit1) != 0) perror("can't register my_exit1"); if (atexit(my_exit1) != 0) perror("can't register my_exit1"); printf("main is done\n"); return 0;}
static void my_exit1(void) { printf("first exit handler\n");}
static void my_exit2(void) { printf("second exit handler\n");}
Example of exit handlers
© 숙대 창병모 12
프로세스 구조
What is a process ?
a process is an executing program together with the program's data, stacks, user-area information about the program in kernel
a process image is the layout of a process in memory
a process is not a program by itself
13
Components of Process Code area
the executable code of a process
Data area static and global variables heap area
Stack area runtime stack to hold activation records including
local variables
Kernel data structures to keep information
one process table in kernel a user area per process
information like open fds, signal actions, etc 14
Components of Process
15
Heap
Stack
Code
User-area
Kernel processes and user processes
User process process in user mode a system call make it into kernel mode
Kernel process process in kernel mode the code is linked directly into the kernel
16
© 숙대 창병모 17
프로세스 생성
System Calls : Creating a new process
새로운 프로세스 생성 자기복제
int fork( ) Create a new process (child process)
An almost-exact duplicate of the parent process
code, data, stack, open file descriptors, etc.
18
© 숙대 창병모 19
fork()
fork() is called once, but returns twice! returns 0 in child process returns the child process ID in parent process Returns -1 on failure.
Execution Parent and child continue executing instructions
following the fork() call
Often, fork() is followed by exec()
System Calls : Creating a new process
20
main() {...rtn = fork();...}
HEAP
STACK
USER AREA
CODE
main() {...rtn = fork();...}
HEAP
STACK
USER AREA
CODE
BEFORE fork()
AFTER fork()
pid: 12791
pid: 12791 pid: 12792
main() {...rtn = fork();...}
HEAP
STACK
CODE
USER AREA
System Calls
Process idint getpid( )
return a process's idint getppid( )
return a parent process's id
int exit (int status) a process may terminate process by executing exit() frees its code, data, stack and closes a process's fds, sends its parent a SIGCHLD signal
21
System Calls
Orphan process If a parent dies before its child, the child is called an
orphan process and is adopted by "init" process, PID 1. it is dangerous for a parent to terminate without waiting
for the death of its child.
22
System Calls
int wait(int* status) wait() causes a process to suspend until one of its
children terminate wait() returns the pid of the child that terminated and places a status code into *status
23
fork()
exit()exec()
wait()
Example : fork and wait
#include <stdio.h>main( ){
int pid, status, childPid;printf(“I’m the parent process and my PID is %d\n”, getpid( ));pid = fork( );if (pid != 0) { printf(“I’m the parent process with PID %d and PPID %d\n”,
getpid( ), getppid( )); childPid = wait(&status); printf(“A child with PID %d terminated with exit code %d\n”
childPid, status>>8);} else {
printf(“I’m the child process with PID %d and PPID %d\n”,getpid( ), getppid( ));
exit(42);}
printf(“PID %d terminates\n”);}
24
© 숙대 창병모 25
프로그램 실행
© 숙대 창병모 26
Program Execution: exec()
프로세스 내의 프로그램을 새 프로그램으로 대치 exec() 시스템 호출 사용 보통 fork() 후에 exec( )
When a process calls an exec function that process is completely replaced by the new
program (text, data, heap, and stack segments) and the new program starts at its main function Successful exec never returns !
프로세스 내에서 새 프로그램 실행
27
...
execl(“newpgm”, …);...
HEAP
STACK
USER AREA
CODE
main() // newpgm {...
...}
HEAP
STACK
USER AREA
CODE
BEFORE exec( ) AFTER exec() pid: 12791 pid: 12791
System Calls:Exec
Replace the calling process's code, data, and stack with
the new program path and execute the new code.
Return a successful exec( ) never returns failure : -1
28
int execl(char* path, char* arg0, char* arg1, ... , char* argn, NULL)int execv(char* path, char* argv[ ])
Example : fork and exec
Call exec( ) after calling fork( ) Create a new process and execute a program
#include <stdio.h>main( ){
int fork( );if (fork( ) == 0) {
execl("/bin/echo", "echo", "this is message one", NULL);perror("exec one faild"); exit(1);
}if (fork( ) == 0) {
execl("/bin/echo", "echo", "this is message two", NULL);perror("exec two faild"); exit(2);
}if (fork( ) == 0) {
execl("/bin/echo","echo", "this is message three",NULL);perror("exec three faild"); exit(3);
}printf("Parent program ending\n");
}29
Etc
Changing directoryint chdir (char* pathname)
set a process's current working directory to pathname the process must have execute permission for the directory returns 0 if successful; otherwise -1
Accessing user and group ids int getuid() int setuid(int id) int geteuid() int seteuid(int id) int getgid() int setgid(int id) int getegid() int setgid(int id)
returns the calling process's real and effective user or group ids
30
Example
#include <stdio.h>
main( ){
system(“pwd”);chdir(“/”);system(“pwd”);chdir(“/user/faculty/chang”);system(“pwd”);
}
31
Example: Background Processing
Execute a program in the background using fork( ) and exec( )
No waiting
#include <stdio.h>main(argc, argv)int argc, argv[ ];{
if (fork( ) == 0) { execvp(argv[1], &argv[1]); fprintf(stderr, “Could not execute %s\n”,argv[1]);}
}32
Redirection 구현
%redirect output command
1) The parent forks and then waits for the child to terminate
2) The child opens the file "output“, and
3) Duplicates the fd of “output" to the standard output(fd=1), and close the fd of the original file
4) The child execute the “command”.
All of the standard output of the command goes to "output“
5) When the child shell terminates, the parent resumes
33
Example: Redirection
%redirect out ls –l#include <stdio.h>main(argc, argv)int argc, argv[ ];{
int fd, status;if (fork() == 0) {
fd=open(argv[1], O_CREAT|O_TRUNC|O_WRONLY, 0600)
dup2(fd, 1);close(fd);execvp(argv[2], &argv[2]);perror(“main”);
} else {
wait(&status);printf(“Child is done\n”);
}}
34
© 숙대 창병모 35
시그널 (Signal)
Signals
Unexpected events a floating-point error a power failure an alarm clock the death of a child process a termination request from a user (Ctrl-C) a suspend request from a user (Ctrl-Z)
36
ProcessSignal #8
Predefined signals
31 signals /usr/include/signal.h See the table in page 427
Actions of the default signal handler terminate the process and generate a
core(dump) ignores and discards the signal(ignore) suspends the process (suspend) resume the process
37
Terminal signal
Terminal signals Control-C
SIGINT signal Control-Z
SIGSTP signal
Requesting an alarm signal SIGALRM signal Default handler
display message “Alarm clock”
38
Example : Alarm
Alarm.c
#include <stdio.h>main( ){
alarm(3);printf(“Looping forever …\n”);while (1);printf(“This line should never be
executed\n”);}
39
Handling Signals: signal( )
Signal handler 등록
signal(int sigCode, void (*func)( ))) specify the action for a signal
sigCode func func
SIG_IGN SIG_DFL user-defined function
return the previous func
40
Handling Signals: Example
#include <stdio.h>#include <signal.h>int alarmFlag=0;alarmHandler( );main( ) {
signal(SIGALRM, alarmHandler);alarm(3);printf(“Looping …\n”);while(!alarmFlag) {
pause( ); } printf(“Loop ends due to alarm signal \n”);} /* main */
alarmHandler( ) {printf(“An alarm clock signal was received\n”);alarmFlag = 1;
} 41
Example: Protecting Critical Code
#include <stdio.h>#include <signal.h>main ( ) {
int (*oldHandler)( );printf(“I can be Control-C’ed\n”);sleep(3);oldHandler = signal(SIGINT, SIG_IGN);printf(“I’m proctected from Control-C now\n”);sleep(3);signal(SIGINT, oldHandler);printf(“I can be Control-C’ed again\n”);sleep(3);
}
42
Sending signals: kill()
프로세스에 Signal 보내기
int kill(int pid, int sigCode) send signal sigCode to the process pid condition for success
the owner of the sending process = the owner of pid
the owner of the sending process = super-user
43
Example: Time Limit #include <stdio.h>#include <signal.h>int delay;main(argc, argv)int argc; char *argv[ ];{
int pid;signal(SIGCHLD,childHandler);pid = fork();if (pid == 0) {
execvp(argv[2], &argv[2]);perror(“Limit”);
} else {sscanf(argv[1], “%d”, &delay);sleep(delay);printf(“Child %d exceeded limit and is being killed\n”, pid);kill(pid, SIGINT);
}} 44
Example: Time Limit
childHandler( ) /* Executed if the child dies before the parent */{
int childPid, childStatus;childPid = wait(&childStatus);printf(“Child %d terminated within %d seconds\n”, childPid, delay);exit(0);
}
Usage%limit 5 ls%limit 4 sleep 100
45
Example: Suspending and Resume#include <signal.h>#include <stdio.h>main( ) {
int pid1, pid2;
pid1 = fork( );if (pid1 == 0) {
while(1) { printf(“pid1 isalive\n”); sleep(1); }}
pid2 = fork( );if (pid2 == 0) {
while (1) { printf(“pid2 is alive\n”); sleep(1); }}
sleep(3); kill(pid1, SIGSTOP);sleep(3); kill(pid1, SIGCONT);sleep(3); kill(pid1, SIGINT);kill(pid2, SIGINT);
} 46
© 숙대 창병모 47
시스템 시작
© 숙대 창병모 48
시스템 시작
The First Process the first process(sched) with pid =0 is created during boot
time, and fork/exec twice.
0 sched1 init2 pagedaemon
Process ID 0 : swapper (scheduler process) system process part of the kernel no program on disk corresponds to this process
© 숙대 창병모 49
시스템 시작 Process ID 1: init process
invoked by the kernel (/etc/init or /sbin/init) reads the system initialization files (/etc/rc*)
brings the system to a certain state (multi-user) creates processes based upon script files getty, login process, mounting file systems, start daemon processes
Process ID 2: pagedaemon supports the paging of the virtual memory system kernel process
© 숙대 창병모 50
The process hierarchy
getty process(/etc/getty) detects line activity and prompts with login exec /bin/login, after entering a response to the
login prompt.
login process checks a user's login and password against
/etc/passwd exec /bin/sh or /bin/csh set the evnironment variables like HOME,
LOGNAME, PATH...
shell process initially read commands form start-up files like
/etc/.cshrc and $HOME/.cshrc shell starts its job
© 숙대 창병모 51
The process hierarchy
sched(0)
pagedaemon(2)init(1)
getty(10)
login(10)
shell(10)
httpd(5) …
© 숙대 창병모 52
Process Identifiers
none of these functions has an error return
#include <sys/types.h>#include <unistd.h>
pid_t getpid(void); // returns process IDpid_t getppid(void); // returns parent process IDuid_t getuid(void); // returns real user IDuid_t geteuid(void); // returns effective user IDgid_t getgid(void); // returns real group IDgid_t getegid(void); // returns effective group ID