操作系统实践(三)
??本次實踐的內容是關于進程。涉及進程的創建、執行、等待、消除返回。進程是并發執行且相互沒有干擾的。對進程內容的保存用PCB(Process Control Block)結構體。本次實驗涉及到與進程相關的四個系統調用如下:
fork() // 創建進程 exec() // 進程執行 wait() // 進程等待 exit() // 進程退出??下面就來詳細的介紹一下四個系統調用(還是給出老師的課程圖了,太全面了~)
fork()
??fork的返回值大致分兩種:0和非0。0就是子進程,通過返回值就可以區分子進程和父進程從而進行對應的操作。
exec()
??exec()實現的時候有兩種:execlp、execvp。這兩種的底層實現不太一樣,lp的代表list鏈表,vp代表vector數組。
??其實每個里面還可以分為兩類:帶不帶p。比如鏈表中其實有兩種實現:execl,execlp。它們兩個的區別如下:
??可以看的出來,帶p的應用更加廣泛。所以此處只舉了帶p的例子。
exit()
wait()
??每節課都有作業,這個當然不能忘啦!
??這個題目其實就是創建子進程實現,主函數里的printf是父進程。每個mysys要想實現就要創建并發的子進程。不創建子進程的話三個橫線就會先輸出。這個代碼按照老師的要求,寫了三版,每一版都是改進。如果著急看代碼可以直接跳過最后,但我把過程記錄下來,便于以后復習。感興趣的也可以看看。
第一版
#include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<sys/types.h> #include<sys/wait.h>void mysys(const char *command) {pid_t pid;if (command == NULL)return ;if ((pid = fork()) < 0) {/*pid < 0代表進程創建失敗,可做相應處理,但此處未做 */ }else if (pid == 0) {/*pid為0代表,創建進程為子進程,可實現執行命令功能 */// execl的第一個參數傳入執行命令路徑,sh代表命令,-c代表之后開始傳入參數 execl("/bin/sh", "sh", "-c", command, NULL);// exit退出進程,退出碼為127 exit(127);}else {/*這種情況是父進程本身,為了讓main中父進程的printf不連續執行,用sleep做延時,給子進程執行時間 */ sleep(1);}return ; }int main() {printf("----------------------\n");mysys("echo Hello world");printf("----------------------\n");mysys("ls /");printf("----------------------\n");return 0; }??這個第一版呢,可以實現功能。但是調用的是shell的功能,相當于還是一個上層的封裝。shell這個命令可以幫助進行字符串的切割,切分出路徑、命令類型、命令參數。所以下一版的改進,主要是針對于字符串切割手動實現。
第二版
#include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<sys/types.h> #include<sys/wait.h> #include<string.h>void mysys (char *command) {int num = 0;char op[512];char arg[512];int a = 0;int b = 0;for (;command[a] != ' '; a++) {op[a] = command[a];}op[a] = '\0';a++;for (;command[a] != '\0'; a++, b++) {arg[b] = command[a];}arg[b] = '\0';pid_t pid;if (command == NULL)return ;if ((pid = fork()) < 0) {}else if (pid == 0) {execlp(op, op,arg, NULL);exit(127);}else {sleep(1);}return ; }int main() {printf("----------------------\n");mysys("echo Hello world");printf("----------------------\n");mysys("ls /");printf("----------------------\n");return 0; }??第二版呢看上去也能運行成功,結果跟想象中一樣。但是其實是不對的,這里面調用的execlp是沒辦法處理不定參數的問題的。輸入多個參數都會被劃到arg這個變量中去。ls 和 echo都沒問題,但對于cp這種就會報錯找不到第二個參數了。所以最終一版使用execvp,能夠實現不定數組功能,具體代碼如下:
#include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<sys/types.h> #include<sys/wait.h> #include<string.h>void mysys(char *command) {char *argv[512]; // 這里必須要用動態指針數組,因為execvp最后有一個NULL作為結束標志,靜態的二維數組是無法實現的。int num = 0;char temp[512];for (int i=0; command[i]!='\0'; i++) {int index = 0;while (command[i]!='\0' && command[i] != ' ') {temp[index++] = command[i++];}temp[index] = '\0';if (command[i] == '\0')break;argv[num] = (char *)malloc(strlen(temp));strcpy(argv[num], temp);num++;}argv[num] = (char *)malloc(strlen(temp));strcpy(argv[num], temp);num++;argv[num] = NULL;pid_t pid;if (command == NULL)return ;if ((pid = fork()) < 0) {}else if (pid == 0) {execvp(argv[0], argv);exit(127);}else {sleep(1);}return ; }int main() {printf("----------------------\n");mysys("echo Hello world");printf("----------------------\n");mysys("ls /");printf("----------------------\n");mysys("cp mysys.c mysys1.c");return 0; }??第三次結束了,但其實還是留下了好多問題一知半解。后面再陸續學習補充吧!
因作者水平有限,如果錯誤之處,請在下方評論區指正,謝謝!
總結
- 上一篇: ubuntu16.04搞出百度的方法
- 下一篇: Qt:Windows编程—Qt实现本地服