Download presentation
Presentation is loading. Please wait.
1
system(const char *string)
Execute system command
2
#include <stdlib.h>
#include <stdio.h> int main() { printf("Running ps with system\n"); system("ps -ax"); printf("Done.\n"); exit(0); }
3
#include <stdlib.h>
#include <stdio.h> int main() { printf("Running ps with system\n"); system("ps -ax &"); printf("Done.\n"); exit(0); }
4
Exec family int execl( const char *path, const char *arg, ...); int execlp( const char *file, const char *arg, ...); int execle( const char *path, const char *arg , ..., char * const envp[]); int execv( const char *path, char *const argv[]); int execvp( const char *file, char *const argv[]); The exec family of functions replaces the current process image with a new process image.
5
Meaning of different letters:
l: needs a list of arguments. v: needs an argv[] vector (l and v are mutually exclusive). e: needs an envp[] array. p: needs the PATH variable to find the executable file
6
#include <stdio.h>
#include <unistd.h> int main () { printf("Calling execl...nn"); execl("/bin/cat", "cat", "./example-1.c", NULL); printf("Useless call to printf"); }
7
行程管理 已進入執行階段的程式稱之為『行程』(Process,或程序)。 簡單的說,程序即是執行中的程式。
行程在執行當中會隨著需要產生(fork)其他子行程(Child Process),並給於子行程執行生命及執行工作項目。 既然『行程』是執行中的獨立程式,當他被執行時,所有主機系統的資源都可被它所存取,至於控制主機資源的程度,則在於該行程的權限等級如何,而與系統中多少行程無關。
8
行程命令 建立(fork):行程可以執行 fork 系統呼叫,來產生另一個子行程(Child Process),而產生行程者則稱為『父行程』(Parent Process)。 行程必定是由另一個行程所產生,而無法自行產生。 產生子行程的原因可以接發生特殊原因或接受命令。
9
fork() is defined at <unistd.h>
#include <stdio.h> #include <unistd.h> int main () { printf("Hello World\n"); fork(); printf("Goodbye Cruel World\n"); }
10
『行程』的特性 Each has a unique PID. Some special PIDs: 0: scheduler 1: init
2: pagedaemon
11
getpid() will return calling process’s pid.
#include <stdio.h> #include <unistd.h> int main() { fork(); printf("\nHello, I am the process with ID = %d\n", getpid()); return 0; }
12
Parent /child process 當使用者以fork系統呼叫產生一個新的處理程序(process),這個處理程序會承襲其親代(parent)的特性(code, stack…)。 此時叫用 fork 系統呼叫的那個處理程序稱為父處理程序,而衍生(fork)出的那個處理程序即為子處理程序(child process)。
13
#include <stdio.h>
#include <unistd.h> int main () { int pid, num=2; printf("Hello World\n"); pid = fork(); if(pid != 0) printf("I'm the Father and my son's PID is %d, num= %d\n",pid, num); else printf("I'm the Son, num=%d\n", num); printf("Goodbye Cruel World\n"); } father return child's pid, child process return 0, fail return -1
14
getppid() will return father’s pid of calling process.
#include <unistd.h> #include <stdlib.h> #include <stdio.h> int main(void) { pid_t pid; if ((pid = fork()) > 0) printf("I am the parent, my pid = %u, my child’s pid = %u\n", getpid(), pid); else if (pid == 0) printf("I am the child, my pid = %u, my parent’s pid = %u\n", getpid(), getppid()); else { perror("fork"); return 1; } return 0;
15
行程的基本生命週期(圖)
16
行程的生命週期 (1) 執行狀態(Running State):行程已佔有 CPU,CPU 正在執行該行程。
(2) 預備狀態(Ready State):行程正準備給 CPU 執行,並已取得執行中所需的資源。 (3) 等待狀態(Wait State):行程在 CPU 執行當中可能欠缺某些資源或逾時而退出,並處於等待索取其他資源狀態;當行程取得所需資源或時間到達,則可進入預備狀態,隨時接受 CPU 處理。
17
行程的生命週期 (4) 停止狀態(Stop State):行程已完成執行,並等待被撤銷。
(5) 死結狀態(Deadlock State):行程等待可能一個永遠無法得到的資源,而繼續無止境的等待。
18
行程生命週期歸納如下 一個父行程呼叫 fork() 系統呼叫產生了一個子行程,並給予該行程的生命(譬如,植入 vi 執行程式),子行程進入『預備』佇列,等待被 CPU 執行。 當該行程取得 CPU 執行之後,如果在『時間片段』中未能執行完畢的話,則可能被踢出到預備狀態,等待下一次被執行的機會;也有可能在執行當中欠缺某些資源而轉換到『等待』狀態,等待取得其他資源;也有可能在時間片段裡執行完畢,而變遷到『停止』狀態。
19
行程的生命週期 同一時間也許會有多個行程進入同一狀態底下,等待改變進入另一個狀態或者被選擇執行。
因此,系統針對每一種狀態建立一個管理制度,才能由眾多行程中選擇一個再改變其狀態; 一般簡單的做法,即是建立一個佇列(Queue),已先進先出的方法,讓先進入該狀態的行程,能先進入下一個狀態。
20
改變行程狀態的因素 可區分為行程命令與系統環境兩大因素。 前者為使用者(或系統)所下達的命令;後者為行程因系統環境的改變,而變遷其狀態。
21
行程命令 撤銷(Destroy):無論行程是正常停止或非正常停止,都須經過撤銷命令來取回行程所占用的記憶體空間,或其他所持有的資源。
阻斷(Block):行程從執行狀態轉變到等待狀態。 停止(Stop):在正常情況下,行程執行完畢之後,會進入停止狀態並等待系統撤銷它。但某些情況,系統也可以執行停止命令,來停止某一個執行當中的行程,並使其進入停止狀態。 喚醒(Wakeup):行程由等待狀態轉換到執行狀態。
22
Process termination exit function: To terminate a process with an exit code. Notice that this is a library, and _exit is a system call. Normal termination: The main program returns. The program calls exit. The program calls _exit. Abnormal termination: The program calls abort. The program catches a signal.
23
#include <unistd.h>
#include <stdlib.h> #include <stdio.h> int main(void) { pid_t pid; pid = fork(); if (pid>0) { printf("daemon on duty!\n"); exit(0); } else if (pid<0) { printf("Can't fork!\n"); exit(-1); } for (;;) { printf("I am the daemon!\n"); sleep(3); /* do something your own here */
24
#include <sys/types.h>
#include <unistd.h> #include <stdio.h> int main() { pid_t pid; char *message; int n; printf("fork program starting\n"); pid = fork(); switch(pid) case -1: perror("fork failed"); exit(1); case 0: message = "This is the child"; n = 5; break; default: message = "This is the parent"; n = 3; } for(; n > 0; n--) { puts(message); sleep(1); exit(0);
25
Process termination When the parent terminates before the child, the init process becomes the parent of this orphan process. When the child terminates before the parent, the child becomes a zombie (defunct). A zombie is a dead entity, but not completely dead,. : The child must leave sufficient information in the process table so that later when its parent wants to fetch its status, it is able to do so, The information a zombie keeps in the process table includes process id, termination status, and accounting information.
26
#include <unistd.h>
#include <stdlib.h> #include <stdio.h> int main(void) { pid_t pid; int i =0; pid = fork(); if (pid>0) { printf ("this is parent, my pid = %d\n", getpid()); printf("parent exits first \n"); exit(0); } sleep(1); for (i =0; i<=10000; i++) ; printf(" this is son, my parent’s pid =%d \n", getppid() );
27
#include <unistd.h>
#include <stdlib.h> #include <stdio.h> int main(void) { pid_t pid; int i =0, j=0; pid = fork(); if (pid==0) { printf ("this is son, my pid = %d\n", getpid()); printf("Son exits first \n"); exit(0); } sleep(1); for (i =0; i<=10000; i++) for(j=0; j<=10000; j++) ; printf("parent exits now \n");
28
wait families wait A process can call wait to wait for the child process to complete. The wait function provides a integer buffer for receiving the termination status. The wait function will block if no child is available. The return value is the process id of the child process. waitpid A process can call wait to wait for a particular child process to complete. The waitpid can be non-blocking.
29
Avoid zombie process pid_t wait(int *stat_loc)
The wait() call is used to tell a process to wait for one of his childs to end before going on with it's own task. wait() takes the adress of an int, in wich it puts the exit status of the child it waited for (to know what you can do with that status, look at 'man wait')
30
#include <stdio.h>
#include <unistd.h> int main() { fork(); printf("\nHello, I am the process with ID = %d\n", getpid()); wait(); return 0; }
31
#include <stdio.h>
#include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include <sys/wait.h> int main( int argc, char *argv[], char *env[] ) { pid_t my_pid, parent_pid, child_pid; int status; /* get and print my pid and my parent's pid. */ my_pid = getpid(); parent_pid = getppid(); printf("Parent: my pid is %d\n", my_pid); printf("Parent: my parent's pid is %d\n", parent_pid); /* print error message if fork() fails */ if((child_pid = fork()) < 0 ) perror("fork failure"); exit(1); } /* fork() == 0 for child process */ if(child_pid == 0) { printf("\nChild: I am a new-born process!\n"); printf("Child: my pid is: %d\n", my_pid); printf("Child: my parent's pid is: %d\n", parent_pid); printf("Child: I am going to execute - date - command \n");
32
execl("/bin/date", "date", 0, 0);
perror("execl() failure!\n"); printf("This print is after execl() and should not get executed\n"); _exit(1); } /* * parent process */ else { printf("\nParent: I created a child process.\n"); printf("Parent: my child's pid is: %d\n", child_pid); system("ps -aclf | grep ercal; exit"); wait(&status); /* can use wait(NULL) since exit status from child is not used. */ printf("\nParent: my child is dead. I am going to leave.\n"); return 0;
33
雖然在一部主機系統內有多個行程『同時』執行中,但『中央處理機』(CPU) 在某一時間內僅能處理一個行程的工作。
Race condition: Multiple processes running simultaneously could result very strange errors. If the correctness of a program depends on the execution sequence of consisting processes, then we have a race condition.
34
#include <stdio.h>
#include <unistd.h> int main() { int a = 2; printf ("a = %d \n", a); if (!fork()) { a = a+3; printf(" a = %d \n", a); a = a + 3; } else { a = a*3; a = a * 3; } return 0;
35
行程的同步 系統中同時存在著許多行程在執行當中,為了達成某些任務,必須多個行程互相合作才能完成,尤其是共用資源的存取。
如欲達成多個行程相互合作完成任務,最起碼必須使這些行程的工作時序必須一致才行。 雖然系統上有多個行程執行當中,但同一時間 CPU 僅能選擇執行其中一個行程;也就是說,先天上的因素這些行程並不可能達到時序的同步。 這就是我們必須將此先天上不同步的因素,採取某些措施使其達成類似時序同步的功能,這就所謂『同步化』(Synchronization)的問題。
Similar presentations