說到進程,首先要明確的一個概念就是什麼是進程,進程是“a program in execution”。一個進程由如下元素組成:
–程序的上下文(context),它是程序當前執行的狀態
–程序的當前執行目錄
–程序訪問的文件和目錄
–程序的信任狀態或者說訪問權限,比特它的文件模式和所有權
–內存和其他分配給進程的系統資源
本文討論創建進程
最近本人寫了一個關於進程操作的程序,之前對進程有過了解,但是,沒有寫程序,所以總感覺是徘徊在門外,很多東西只是瞭解個大概,在這次真的要寫程序的時候,不知道如何下手。
1、 system函數
在頭文件#include<stdlib.h>中包含
函數原型: int system(const char *command);
功能描述: system()通過調用/bin/sh –c command來執行具體的command命令,在command完成後返回。在command執行期間,SIGCHLD信號被阻塞,SIGINT和SIGQUIT將被忽略。
返回值: 如果沒有找到/bin/sh,system返回127;
如果出現其他錯誤則返回-1;
如果執行成功則返回command的代碼。
但是如果command爲NULL,system返回一個非0值,否則返回0。
示例:
2、 fork系統調用
fork調用創建一個新的進程。新的進程或者說子進程是調用進程的或者說父進程的副本。
Fork的語法是
#include<unistd.h>
pid_t fork(void);
如果fork執行成功,就向父進程返回子進程的PID,並向子進程返回0。這就一起這即使你只調用fork一次,他也會返回兩次。
Fork創建的新進程是和父進程(除了PID和PPID)一樣的副本,包括真實和有效的UID和GID、進程組合會話ID、環境、資源限制、打開的文件以及共享內存段。
父進程和子進程之間有一點區別。子進程沒有繼承父進程的超市設置(使用alarm調用
)父進程創建的文件鎖,或者未決信號。要理解的關鍵概念是fork創建的新進程是父進程的一個準確副本。
2、fork系統調用
fork調用創建一個新的進程。新的進程或者說子進程是調用進程的或者說父進程的副本。
Fork的語法是
#include<unistd.h>
pid_t fork(void);
如果fork執行成功,就向父進程返回子進程的PID,並向子進程返回0。這就一起這即使你只調用fork一次,他也會返回兩次。
Fork創建的新進程是和父進程(除了PID和PPID)一樣的副本,包括真實和有效的UID和GID、進程組合會話ID、環境、資源限制、打開的文件以及共享內存段。
父進程和子進程之間有一點區別。子進程沒有繼承父進程的超市設置(使用alarm調用)父進程創建的文件鎖,或者未決信號。要理解的關鍵概念是fork創建的新進程是父進程的一個準確副本。
示例:
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void)
{
pid_t child;
if((child = fork()) == -1)
{
perror("fork");
exit(EXIT_FAILURE);
}
else if(child == 0) //子進程中
{
puts("in child");
printf("\tchild pid = %d\n",getpid());
printf("\tchild ppid = %d\n",getppid());
exit(EXIT_SUCCESS);
}
else
{
puts("in parent");
printf("\tparent pid = %d\n",getpid());
printf("\tparent ppid = %d\n",getppid());
}
exit(EXIT_SUCCESS);
}
3、 exec函數族
與fork函數一樣,exec也在<unistd.h>中聲明。它的原型爲:
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 *constargv[]);
int execvp(const char *file, char *constargv[]);
int execve(const char *path, char *constargv[], char *const envp[]);
exec用被執行的程序完全替換了調用進程的映像。Fork創建了一個新進程就產生了一個新的PID,exec啓動一個新程序,替換原有進程。因此被執行的進程的PID不會改變。
例如:
int execve(const char *path, char *constargv[], char *const envp[]);
接收三個參數:
path是要執行的二進制文件或腳本的完整路徑。
argv是要傳遞給程序的完整參數列表,包括argv[0],它一般是執行程序的名字,
envp是指向用於執行execed程序的專門環境的指針。
這幾個函數可以簡單討論如下:
名字中含有l的函數:希望接受以逗號分隔的參數列表,列表以NULL指針作爲結束標誌,這些參數將傳遞給被執行的程序。
名字中包v的函數:則接受一個向量,也就是以空結尾的字符串的指針數組。這個數組必須以一個NULL指針作爲結束標誌。
不過,需要注意的是,有時候可能那個NULL,需要寫成(char *)0。
//一個創建num個進程的示例:
//其中batchscript是已經寫好的shell腳本文件。
void createsubprocess(int num)
{
int i;
int child;
int pid[num];
for(i=0;i<num;i++)
{
if((child = fork()) == -1)
{
perror("fork");
exit(EXIT_FAILURE);
}
else if(child==0) //子進程運行
{
pid[i]=getpid();
if(execl("/usr/audio/./batchscript","./batchscript",(char *)0) == -1 )
{
perror("execl");
exit(EXIT_FAILURE);
}
}
else
{
}
}
for(i=0;i<num;i++)
{
waitpid(pid[i],NULL,0);
}
}
實現了多進程併發。