建立新程序
我們可以通過系統調用來建立一個新的程序。這個系統調用完美的複制了目前程序,并且在程序表中建立了一個新的表項,新表項有很多屬性與目前項目是相同的。新的程序與原來的程序幾乎一模一樣,執行的代碼也是完全相同的。但是新的程序有自己的空間環境和檔案描述符等。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TP35keNpWTxElaNBDOsJGcohVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL2YzNzUjN0QTMyEDMxkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
從上面這幅圖我們可以看清,由fork産生的子程序傳回的值為0而原程序傳回一個新的pid。下面我們簡單示範一個fork作用。
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main()
{
pid_t pid = fork();
int n = 0;
if (pid == 0)
{
//子程序執行
n = 5;
printf("this is children\n");
sleep(1);
}
else
{
//父程序執行
n = 3;
printf("this is father\n");
sleep(1);
}
for (int i = 0; i < n; i++){
pirntf("yes\n");
sleep(1);
}
exit(0);
}
僵屍程序
![在這裡插入圖檔描述](https://img-blog.csdnimg.cn/20191012151416710.png
如果我們把上訴代碼做一個修改,我們就能看到僵屍程序如下
if (pid == 0)
{
//子程序執行
n = 3;
printf("this is children\n");
sleep(1);
}
else
{
//父程序執行
n = 5;
printf("this is father\n");
sleep(1);
}
上訴代碼中,子程序先與父程序結束了,父程序沒擷取到子程序的推出碼,是以程序變成了一個僵屍程序。
上圖中我們就可以看到這個僵屍程序。為了解決這個問題,我們采用一種方法,就是調用wait函數來擷取子程序的推出碼。
exec系列程序替換
exec系列有如下幾個函數構成
================================================================*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
#include<unistd.h>
int main(int argc, char * argv[], char *envp[]){
printf("pid = %d \n", getpid());
//char *myargv[10] = {"ps","-f"};
//char *myenvp[10] = {"MYSTR=hello", "VAL=100"};
//execl("/bin/ps", "ps", "-f", (char*)0);
//execlp("ps", "ps", "-f", (char*)0);
//execle("bin/ps", "ps", "-f", (char*)0,myenvp);
//execv("/bin/ps", myargv);
//execvp("ps", myargv);
execl("./main", "main", "hello", "123", (char *)0);
perror("execl error");
exit(0);
}
利用這個函數,我們就可以完成一個簡單的linux下的bash指令。
具體代碼如下:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<sys/types.h>
#include<pwd.h>
#define MAX_NUM 10
#define PATH "/home/ma/01-圖論c++/02-linux學習/08-fork等程序/mybin/"
void PrintInfo(){
int uid = getuid();
char *s = "$";
if (uid == 0){
s = "#";
}
struct passwd *ptr = getpwuid(uid);
if (ptr == NULL){
printf("mybash>>$");
fflush(stdout);
return;
}
char hostname[128] = {0};
if (gethostname(hostname, 128) == -1){
printf("myabsh>>$");
fflush(stdout);
return;
}
char dir[256] = {0};
getcwd(dir, 256);
char *last_p = "/";
char *cur_p = strtok(dir, "/");
while(cur_p != NULL ){
last_p = cur_p;
cur_p = strtok(NULL, "/");
}
char *host_name = strtok(hostname, ".");
printf("[%s@%s %s]%s ", ptr->pw_name,host_name, last_p, s);
fflush(stdout);
}
int main(int argc, char *argv[]){
while(1){
PrintInfo();
char buf[128] = {0};
fgets(buf, 128, stdin);
buf[strlen(buf)-1] = 0;
int i = 0;
char *myargv[MAX_NUM] = {0};
char *s = strtok(buf, " ");
while(s != NULL){
myargv[i] = s;
i++;
s = strtok(NULL, " ");
}
if (myargv[0] == NULL){
continue;
}else if(strcmp(myargv[0], "cd") == 0){
if (myargv[1] != NULL){
if( chdir(myargv[1]) == -1){
perror("cd error");
}
}
continue;
}else if (strcmp(myargv[0], "exit") == 0){
exit(0);
}
pid_t pid = fork();
assert(pid != -1);
if (pid == 0){
//execvp(myargv[0], myargv);
char path[256] = {0};
if (strncmp(myargv[0], "/", 1) != 0 && strncmp(myargv[0], "./", 2) != 0){
strcpy(path, PATH);
}
strcat(path, myargv[0]) ;
execv(path, myargv);
perror("exec error");
exit(0);
}
wait();
}
}