系統(tǒng)與網(wǎng)絡(luò)編程
exec的使用
找一個函數(shù):find /usr gedit
- execl 使用
- 調(diào)用系統(tǒng)ls
- int execl(const char *path, const char *arg, ...);
#include <unistd.h> #include <stdio.h> int main() { int ret=-1; //int execl(const char *path, const char *arg, ...); //第一個參數(shù):可執(zhí)行文件的路徑 //之后的參數(shù): ret=execl("/bin/ls","ls","/usr/include","-l",NULL); return 0; } 可查看目標路徑下的文件,功能同ls- 調(diào)用目標./test
ret=execl("./test","test",NULL);- 調(diào)用系統(tǒng)gedit打開文件
ret=execl("/usr/bin/gedit","gedit","exec.c",NULL); - execlp使用
- int execlp(const char *file, const char *arg, ...);
- 可以不指定需要執(zhí)行文件的路徑,啟動該執(zhí)行文件時到系統(tǒng)默認路徑下去找該執(zhí)行文件。若找到了則執(zhí)行,否則出錯返回。
- 直接調(diào)用系統(tǒng)gedit打開文件
#include <unistd.h> #include <stdio.h> int main() { int ret=-1; ret=execlp("gedit","gedit","exec.c",NULL); }- 調(diào)用沒有的文件
ret=execlp("myText","myTest",NULL); printf("ret=%d\n",ret); if(ret==-1) { perror("execlp"); return -1; } //no such file or directory
- execv使用
//int execv(const char *path, char *const argv[]); #include <unistd.h> #include <stdio.h> int main() { int ret=-1; char *const argv[]={"ls","/usr/include","-l",NULL}; ret=execv("/bin/ls",argv); return 0; } - execvp
// int execvp(const char *file, char *const argv[]); #include <unistd.h> #include <stdio.h> int main() { int ret=-1; char *const argv[]={"gedit","exec.c",NULL}; ret=execvp("gedit",argv); return 0; } - 實現(xiàn)如終端下后臺運行操作
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main(int argc,char *argv[])
{
pid_t pid=-1;
pid=fork();
if(pid>0)//parent
{
while(1)
{
printf("this is parent\n");
sleep(1);
}
}
else if (pid==0)
{
execv(argv[1],argv+1);//第三個開始都是它的參數(shù)
//./a.out /bin/ls /usr/include -l
int ret=-1;
if(ret==-1)
{
perror("execv");
return -1;
}
}
return 0;
}

Paste_Image.png

Paste_Image.png
- 終端模擬
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
char *getInput(char *argv[])//從終端接受字符
{
int i=0;
int ret=-1;
char *pData=NULL;
pData=(char *)malloc(64);
while(EOF!=scanf("%s",pData))//
{
argv[i]=pData;
pData=(char *)malloc(64);
i++;
}
free(pData);
argv[i]=NULL;
return NULL;
}
void showArgv(char *argv[])
{
int i=0;
while (argv[i]!=NULL)
{
printf("%s\n",argv[i]);
i++;
}
}
int main(void)
{
char *argv[32]={NULL};
while(1)
{
printf("myTermal@suhui$:");
getInput(argv);
pid_t pid=-1;
pid=fork();
if(pid>0)
{
wait(NULL);
}
else if(pid==0)
{
pid_t pid2=fork();
if(pid2==0)
{
int ret=-1;
ret=execvp(argv[0],argv);
if(ret==-1)
{
perror("execvp");
return -1;
}
}
return 0;
}
}
#if 0
if(pid>0)//parent
{
while(1)
{
printf("MyTermal:");
getInPut(argv);//循環(huán)輸入
pid_t pid2=-1;
pid2=fork();//循環(huán)創(chuàng)建子進程
if(pid2==0)
{
int ret=-1;
ret=execv(argv[0],argv);
}
}
}
else if (pid==0)
{
execv(argv[1],argv+1);//第三個開始都是它的參數(shù)
//./a.out /bin/ls /usr/include -l
int ret=-1;
if(ret==-1)
{
perror("execv");
return -1;
}
}
return 0;
#endif
}
- 進程的自殺
- return 0 后繼續(xù)執(zhí)行用atexit
- 進程正常結(jié)束時首先在用戶態(tài)做一些善后工作,然后進入內(nèi)核層做一些善后工作
#include <stdio.h> #include <stdlib.h> void fun1() { printf("fun1....\n"); } void fun2() { printf("fun2....\n"); } void fun3() { printf("fun3....\n"); } int main() { atexit(fun1); atexit(fun2); atexit(fun3); printf("hello world\n"); return 0;//實現(xiàn)return 0后要執(zhí)行的代碼,atexit. }-
atexit注冊函數(shù)會在進程正常結(jié)束后被執(zhí)行,執(zhí)行的順序與注冊順序相反
Paste_Image.png - exit(-1):程序自殺
int main() { atexit(fun1); atexit(fun2); atexit(fun3); exit(-1);//自殺 printf("hello world\n"); return 0;//實現(xiàn)return 0后要執(zhí)行的代碼,atexit. }Paste_Image.png- abort:程序非正常結(jié)束
int main() { atexit(fun1); atexit(fun2); atexit(fun3); abort(); printf("hello world\n"); return 0;//實現(xiàn)return 0后要執(zhí)行的代碼,atexit. }- _exit():直接進入內(nèi)核做善后工作
int main() { atexit(fun1); atexit(fun2); atexit(fun3); _exit(); printf("hello world\n"); return 0;//實現(xiàn)return 0后要執(zhí)行的代碼,atexit. }
進程間通信
- ipc:interprocess communication
通信方式
-
管道通信
Paste_Image.png- 無名管道:通過pipe創(chuàng)建出來的管道,只能在父子進程或子進程間使用,創(chuàng)建該管道的進程一旦結(jié)束,則該無名管道也會銷毀
#include <unistd.h>//pipe #include <stdio.h> #include <string.h> //通過pipe創(chuàng)建的管道屬于無名管道 //只能在父子進程或子進程間使用 //創(chuàng)建該管道的進程一旦結(jié)束,則該無名管道也會銷毀 int main() { int pipefd[2]={-1};//管道文件描述符 int ret=-1; ret=pipe(pipefd);//創(chuàng)建的管道是位于內(nèi)核空間的,管道兩端的描述符存儲到pipe數(shù)組 //pipefd[0]表示數(shù)據(jù)流出段,可以從此端讀取數(shù)據(jù) //pipefd[1]表示數(shù)據(jù)進入段,可以從此端寫入數(shù)據(jù) if(ret==-1)//創(chuàng)建管道失敗 { perror("pipe"); return -1; } //創(chuàng)建一個進程 pid_t pid=-1; //管道的創(chuàng)建是創(chuàng)建在內(nèi)核中,不屬于獨立進程 //fork產(chǎn)生的子進程是不會再創(chuàng)建一個管道 //只是對管道文件進行了一次拷貝 pid=fork(); if(pid>0)//parent { int iSign=0; char caBuf[32]={'\0'}; while(1) { memset(caBuf,'\0',sizeof(caBuf)); if(iSign==0) { printf("parent input data\n"); scanf("%s",caBuf); write(pipefd[1],caBuf,sizeof(caBuf)); iSign=1; sleep(1); } else if(iSign==1) { read(pipefd[0],caBuf,sizeof(caBuf)); printf("child says:%s\n",caBuf); iSign=0; } } } else if(pid==0)//child { int iSign=1; char caBuf[64]={'\0'}; while(1) { memset(caBuf,'\0',sizeof(caBuf)); if(iSign==1) { read(pipefd[0],caBuf,sizeof(caBuf)); printf("parent says:%s\n",caBuf); iSign=0; } else if(iSign==0) { printf("child input data\n"); scanf("%s",caBuf); write(pipefd[1],caBuf,sizeof(caBuf)); iSign=1; sleep(1); } } } else if(pid==-1)//fork failed { perror("fork"); return -1; } return 0; }- 命名管道:
- 父進程輸出關(guān)閉子進程的輸出,打開輸入。子進程輸出關(guān)閉父進程的輸出,打開輸入。
homework
- 進程的狀態(tài)及狀態(tài)間的轉(zhuǎn)化
- 進程的狀態(tài)有:就緒態(tài),執(zhí)行態(tài),阻塞態(tài)。
- 就緒→執(zhí)行
處于就緒狀態(tài)的進程,當進程調(diào)度程序為之分配了處理機后,該進程便由就緒狀態(tài)轉(zhuǎn)變成執(zhí)行狀態(tài)。 - 執(zhí)行→就緒
處于執(zhí)行狀態(tài)的進程在其執(zhí)行過程中,因分配給它的一個時間片已用完而不得不讓出處理機,于是進程從執(zhí)行狀態(tài)轉(zhuǎn)變成就緒狀態(tài)。 - 執(zhí)行→阻塞
正在執(zhí)行的進程因等待某種事件發(fā)生而無法繼續(xù)執(zhí)行時,便從執(zhí)行狀態(tài)變成阻塞狀態(tài)。 - 阻塞→就緒
處于阻塞狀態(tài)的進程,若其等待的事件已經(jīng)發(fā)生,于是進程由阻塞狀態(tài)轉(zhuǎn)變?yōu)榫途w狀態(tài)。
- 就緒→執(zhí)行
- 進程的狀態(tài)有:就緒態(tài),執(zhí)行態(tài),阻塞態(tài)。
- 完善目錄拷貝
- 獨立完成模仿終端的代碼
- 通過無名管道,讓兩個子進程間完成相互通信工作


