通過調用fork和exec函數都能創建新的進程,但兩者有著本質的區別:fork函數拷貝了父進程的內存映像,而exec函數用用新的映像來覆蓋調用進程的進程映像的功能。
一? fork函數
#include <unistd.h>
pid_t fork(void); //創建子進程成功時,向子進程返回0,并將子進程的進程ID返回給父進程
//創建失敗時,返回-1,并將errno設置為EAGAIN
返回值是允許父進程和子進程區別自己并執行不同代碼的關鍵特征。
#include <stdio.h>
#include
<unistd.h>
#include
<sys/types.h>
int
main(
void
){
pid_t childpid;
//子進程的ID
childpid
=
fork();
//創建子進程
if
(childpid==-
1
){ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
//創建子進程失敗
perror(
"
Failed to fork
"
);
return
1
;
}
if
(childpid==
0
){ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
//創建子進程成功
printf(
"
I am child %ld\n
"
,(
long
)getpid()); ? ? ?
//打印子進程的ID
}
else
{
printf(
"
I am parent %ld\n
"
,(
long
)getpid()); ? ?
//打印父進程的ID
}
}
?
二 exec函數
有六種不同形式的exec函數,如下:
#include <unistd.h>
int
execl(
const
char
*path, ? ?
//進程映像文件的路徑名,可以是全限定路徑名,也可以是相對于當前目錄的路徑名
const
char
*arg,...
);
int
execle(
const
char
*path,
const
char
*arg,...,
char *const envp[]
); ? ?
//最后一個參數必須以空指針(NULL)作結束
int
execlp(
const
char
*file,
const
char
*arg,...
);
int
execv(
const
char
*path,
char
*
const
argv[]);
//參數數組,用來存放指向你的字符串參數的指針數組
int
execve(
const
char
*path,
char
*
const
argv[],
char
*
const
envp[]);
int
execvp(
const
char
*file,
char
*
const
argv[]);
execv開頭的函數是把參數以"char *argv[]"這樣的形式傳遞命令行參數。而execl開頭的函數采用了我們更容易習慣的方式,把參數一個一個列出來,然后以一個NULL
表示結束,也可以寫成(char *)0。
如果創建子進程不成功,所有的exec函數都返回-1,并設置errno,以下是errno的類型和原因。
E2BIG:新進程的參數表和環境表長度以系統所允許的ARG_MAX字節的限制要長
EACCES:對新進程路徑前綴中目錄的搜尋權限被否定,新進程映像文件的執行權限被否定,或者新進程映像文件不是正常的文件,且不能被執行
EINVAL:新進程映像文件有恰當的權限,且以可識別可執行的二進制格式出現
ELOOP:在對參數path或file進行解析時存在循環
ENAMETOOLONG:path或file的長度超出了PATH_MAX的范圍,或者路徑名組件比NAME_MAX要長
ENOENT:path或file組件命名的不是一個現存的文件,或者path或file為空字符串
ENOEXEC:映像文件有恰當的訪問權限,但它的格式不可識別(不適用于execlp或execvp)
ENOTDIR:映像文件路徑前綴的組件不是一個目錄
int
main(
int
argc,
char
*argv[],
char
*
envp[])
{
char
*arg[]={
"
ls
"
,
"
-a
"
,NULL};
if
(fork()==
0
)
{
printf(
"
execl...........\n
"
);
if
(execl(
"
/bin/ls
"
,
"
ls
"
,
"
-a
"
,NULL)<
0
)
{
fprintf(stderr,
"
execl failed:%s
"
,strerror(errno));
return
-
1
;
}
}
if
(fork()==
0
)
{
printf(
"
execv...........\n
"
);
if
(execv(
"
/bin/ls
"
,arg)<
0
)
{
fprintf(stderr,
"
execl failed:%s\n
"
,strerror(errno));
return
-
1
;
}
}
if
(fork()==
0
)
{
printf(
"
execlp...........\n
"
);
if
(execlp(
"
ls
"
,
"
ls
"
,
"
-a
"
,NULL)<
0
)
{
fprintf(stderr,
"
execl failed:%s
"
,strerror(errno));
return
-
1
;
}
}
if
(fork()==
0
)
{
printf(
"
execvp...........\n
"
);
if
(execvp(
"
ls
"
,arg)<
0
)
{
fprintf(stderr,
"
execl failed:%s\n
"
,strerror(errno));
return
-
1
;
}
}
if
(fork()==
0
)
{
printf(
"
execle...........\n
"
);
if
(execle(
"
/bin/ls
"
,
"
ls
"
,
"
-a
"
,NULL,envp)<
0
)
{
fprintf(stderr,
"
execl failed:%s
"
,strerror(errno));
return
-
1
;
}
}
if
(fork()==
0
)
{
printf(
"
execve...........\n
"
);
if
(execve(
"
/bin/ls
"
,arg,envp)<
0
)
{
fprintf(stderr,
"
execl failed:%s\n
"
,strerror(errno));
return
-
1
;
}
}
return
0
;
}
?
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

