2.linux_进程编程

目录

一、理论

二、编程实战


fork(函数)_百度百科

fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:

(1)在父进程中,fork返回新创建子进程的进程ID;

(2)在子进程中,fork返回0;

(3)如果出现错误,fork返回一个负值

在fork函数执行完毕后,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程。在子进程中,fork函数返回0,在父进程中,fork返回新创建子进程的进程ID。我们可以通过fork返回的值来判断当前进程是子进程还是父进程。

一、理论

问1. 什么是程序,什么是进程,有什么区别?

问2. 如何查看系统中有哪些进程?

问3. 什么是进程标识符?

问4. 什么叫父进程,什么叫子进程?

问5. C程序的存储空间是如何分配?

问1. 什么是程序,什么是进程,有什么区别?

程序是静态的概念,gcc xxx.c –o pro

磁盘中生成pro文件,叫做程序

进程是程序的一次运行活动,

通俗点意思是程序跑起来了,系统中就多了一个进程

问2. 如何查看系统中有哪些进程?

a.使用ps指令查看

实际工作中,配合grep来查找程序中是否存在某一个进程

CLC@Embed_Learn:~/process$ ps -aux | grep init
Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html
root         1  0.0  0.1  24604  2496 ?        Ss   Aug22   0:02 /sbin/init
CLC      44006  0.0  0.0  13592   936 pts/4    S+   12:47   0:00 grep --color=auto init

b.使用top指令查看,类似windows任务管理器

CLC@Embed_Learn:~/process$ top

top - 12:49:58 up 6 days,  6:25,  2 users,  load average: 0.08, 0.10, 0.06
Tasks: 326 total,   1 running, 323 sleeping,   2 stopped,   0 zombie
Cpu(s): 23.1%us,  7.7%sy,  0.0%ni, 69.2%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   2042368k total,  1929468k used,   112900k free,   129160k buffers
Swap:  5998588k total,     5688k used,  5992900k free,  1011552k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                                    
44008 CLC       20   0 17468 1500  976 R   33  0.1   0:00.51 top                                                                                                                        
    1 root      20   0 24604 2496 1348 S    0  0.1   0:02.21 init                                                                                                                       
    2 root      20   0     0    0    0 S    0  0.0   0:00.15 kthreadd                                                                                                                   
    3 root      20   0     0    0    0 S    0  0.0   0:05.18 ksoftirqd/0                                                                                                                
    5 root       0 -20     0    0    0 S    0  0.0   0:00.00 kworker/0:0H                                                                                                               
    7 root      20   0     0    0    0 S    0  0.0  16:09.23 rcu_sched                                                                                                                  
    8 root      20   0     0    0    0 S    0  0.0  13:57.84 rcuos/0                                                                                                                    
    9 root      20   0     0    0    0 S    0  0.0  12:30.63 rcuos/1                                                                                                                    
   10 root      20   0     0    0    0 S    0  0.0  12:54.56 rcuos/2                                                                                                                    
   11 root      20   0     0    0    0 S    0  0.0  12:07.60 rcuos/3                                                                                                                    
   12 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/4                                                                                                                    
   13 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/5                                                                                                                    
   14 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/6                                                                                                                    
   15 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/7                                                                                                                    
   16 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/8                                                                                                                    
   17 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/9                                                                                                                    
   18 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/10                                                                                                                   
   19 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/11                                                                                                                   
   20 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/12                                                                                                                   
   21 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/13                                                                                                                   
   22 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/14                                                                                                                   
   23 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/15                                                                                                                   
   24 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/16                                                                                                                   
   25 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/17                                                                                                                   
   26 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/18                                                                                                                   
   27 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/19                                                                                                                   
   28 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/20                                                                                                                   
   29 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/21                                                                                                                   
   30 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/22                                                                                                                   
   31 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/23                                                                                                                   
   32 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/24                                                                                                                   
   33 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/25                                                                                                                   
   34 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/26                                                                                                                   
   35 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/27                                                                                                                   
   36 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/28                                                                                                                   
   37 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/29                                                                                                                   
   38 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/30                                                                                                                   
   39 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/31                                                                                                                   
   40 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/32                                                                                                                   
   41 root      20   0     0    0    0 S    0  0.0   0:00.00 rcuos/33    

问3. 什么是进程标识符?

每个进程都有一个非负整数表示的唯一ID,

叫做pid,类似身份证

Pid=0:  称为交换进程(swapper)

作用—进程调度

Pid=1:init进程

作用—系统初始化

编程调用getpid函数获取自身的进程标识符

getppid获取父进程的进程标识符

问4. 什么叫父进程,什么叫子进程

进程A创建了进程B

那么A叫做父进程,B叫做子进程,父子进程是相对的概念,理解为人类中的父子关系

问5. C程序的存储空间是如何分配?

        代码段:存放函数体的二进制代码,由操作系统进行管理

        数据段:初始化过的变量

        BSS:函数外来初始化的变量

        堆:malloc申请空间在堆里申请

        栈:函数调用产生以及一些局部变量的信息

 

进程创建实战 

使用fork函数创建一个进程

pid_t fork(void);

fork函数调用成功,返回两次

返回值为0,     代表当前进程是子进程

返回值非负数,代表当前进程为父进程

调用失败,返回-1

fork创建一个子进程的一般目的

fork编程实战 

vfork函数 也可以创建进程,与fork有什么区别 

关键区别一:

vfork 直接使用父进程存储空间,不拷贝。

关键区别二:

vfork保证子进程先运行,当子进程调用exit退出后,父进程才执行。

进程退出

正常退出

1.Main函数调用return
2.进程调用exit(),标准c库
3.进程调用_exit()或者_Exit(),属于系统调用

补充:

1.进程最后一个线程返回
2.最后一个线程调用pthread_exit

异常退出

1.调用abort
2.当进程收到某些信号时,如ctrl+C
3.最后一个线程对取消(cancellation)请求做出响应

等待子进程

为啥要等待子进程退出?

父进程等待子进程退出,并收集子进程的退出状态

子进程退出状态不被收集,变成僵死进程(僵尸进程) 

相关函数

status参数:

是一个整型数指针

非空:

子进程退出状态放在它所指向的地址中。

空:

不关心退出状态

孤儿进程

父进程如果不等待子进程退出,在子进程之前就结束了自己的“生命”,此时子进程叫做孤儿进程

Linux避免系统存在过多孤儿进程,init进程收留孤儿进程,变成孤儿进程的父进程

exec族函数

精彩博文:

https://blog.csdn.net/u014530704/article/details/73848573

 为什么要用exec族函数,有什么作用 ?

exec配合fork使用

实现功能,当父进程检测到输入为1的时候,创建子进程把配置文件的字段值修改掉。

system函数

 

https://www.cnblogs.com/leijiangtao/p/4051387.html 

system()函数的返回值如下:

成功,则返回进程的状态值;

当sh不能执行时,返回127;

失败返回-1;

popen函数

https://blog.csdn.net/libinbin_1014/article/details/51490568 http://3

比system在应用中的好处:

  可以获取运行的输出结果

二、编程实战

二、进程   process
   重点:1 2 3 4 5 12 13

1. demo1 进程的相关概念
2 3. demo2 - demo6 研究父子进程  demo6.1 创建进程函数fork的使用补充
4. demo7 定义一个全局变量 int data = 10,父进程里面不变,子进程里面做改变。
5. demo8  模拟网络创建子进程对接
6. demo9 fork()函数的使用。
   demo10 vfork()函数的使用。
   demo11 进程退出 
7. 进程退出的详解,exit (),_exit()或者_Exit(),包含前两种。
8. 等待子进程退出  
   demo12 僵尸进程   ps -aux|grep newpro 
   demo13 fork()函数 变成僵尸进程。
   demo14 使用wait(NULL)函数,等待子进程结束完之后,在执行父进程。
   demo15 使用 wait(&status);收集子进程的状态码
9. demo16 有问题,父子不能一块输出。 
   demo17 孤儿进程的案例,用linux中的init进程收留孤儿进程,编程孤儿进程的父进程。
10. demo18 echorag 我们先用gcc编译echoarg.c,生成可执行文件echoarg并放在 ./echoarg目录下。
          文件echoarg的作用是打印命令行参数。然后再编译demo18.c并执行a.out可执行文件。
          用 a.out找到并执行echoarg,将当前进程main替换掉,所以"after execl" 没有在终端被打印出来。
    demo19 execl,先使用 whereis ls,查看绝对路径/bin/ls,然后在demo19 中改为如下的代码: if(execl("/bin/ls","ls",NULL,NULL) == -1),
          然后再编译demo19.c并执行a.out可执行文件,即可当whereis ls指令来使用。
    demo20 execl,ls -l指令可以查看文件权限,在demo20中  使用 if(execl("/bin/ls","ls","-l",NULL) == -1),
          然后再编译demo20.c并执行a.out可执行文件,可以当做ls -l 指令来使用。
    demo21 execl,在系统中可以用date指令来查看时间,可以使用whereis date指令来查看绝对路径,然后在demo21中做代码的修改,
            如 if(execl("/bin/date","date",NULL,NULL) == -1)
    demo22 execl,使用ps,if(execl("/bin/ps","ps","-l",NULL) == -1)。
    demo23 execlp,exaclp函数带p,所以能通过环境变量PATH查找到可执行文件ps,if(execlp("ps","ps","-l",NULL) == -1)     带p不需要加绝对路径
    demo24 execvp,把 argv 传到 execvp 中来,char *argv[] = {"ps",NULL,NULL}       if(execvp("ps",argv) == -1)     带p不需要加绝对路径
    demo25  execv,需要加绝对路径if(execv("/bin/ps",argv) == -1)
11. demo26  fork的使用,用demo26中的a./out把config.txt中的数字改为5。
    demo27  exec配合fork使用。   在file文件的demo14,把该代码生成changData,gcc demo14.c -o changData
                  拷贝changData到process文件中,cp ../file/changData .
                  代码就可以执行了,好处是代码简洁
12. demo28  system函数的使用,system("./changData config.txt ");
    demo29  cp demo24 demo29   使用system函数,如果ps写错了如if(system("psxxx") == -1),结果sh: 1: psxxx: not found  等价于指令:sh -c ps112
13. demo30  demo31   popen的用法:可以得到这个指令的运行结果,可以把结果存到字符串数组,也可以写在文件里。    
14. 总结进程

demo1.c

#include <stdio.h> 

#include <sys/types.h>
#include <unistd.h>

int main()
{
	pid_t pid;

	pid = getpid();

	printf("my pid is %d\n",pid);

	while(1);

	return 0;
}

CLC@Embed_Learn:~/process$ gcc demo1.c
CLC@Embed_Learn:~/process$ ./a.out 
my pid is 43885

 demo2.c

#include <stdio.h> 
#include <sys/types.h>
#include <unistd.h>

int main()
{
	pid_t pid;

	pid = getpid();

	fork();

	printf("my pid is %d\n",pid);

	return 0;

}

CLC@Embed_Learn:~/process$ gcc demo2.c
CLC@Embed_Learn:~/process$ ./a.out 
my pid is 43910
my pid is 43910

demo3.c

#include <stdio.h> 
#include <sys/types.h>
#include <unistd.h>

int main()
{
	pid_t pid;

	pid = getpid();

	fork();

	printf("my pid is %d,current pro id:%d\n",pid,getpid());

	return 0;

}

CLC@Embed_Learn:~/process$ gcc demo3.c
CLC@Embed_Learn:~/process$ ./a.out 
my pid is 43939,current pro id:43939
my pid is 43939,current pro id:43940

demo4.c

#include <stdio.h> 
#include <sys/types.h>
#include <unistd.h>

int main()
{
	pid_t pid;

	pid = getpid();

	fork();

	if(pid == getpid()){
		printf("this is father prinf,father pid%d\n",getpid());
	}else{
		
		printf("this is child ,child pid%d\n",getpid());
	}


	return 0;

}

CLC@Embed_Learn:~/process$ gcc demo4.c
CLC@Embed_Learn:~/process$ ./a.out 
this is father prinf,father pid43952
this is child ,child pid43953

demo5.c

#include <stdio.h> 
#include <sys/types.h>
#include <unistd.h>

int main()
{
	pid_t pid;
	pid_t pid2;

	pid = getpid();
	printf("before fork:pid = %d\n",pid);

	fork();
	
	pid2 = getpid();
	printf("after fork:pid = %d\n",pid2);

	if(pid == pid2){
		printf("this is father print\n");
	}else{
		
		printf("this is child ,child pid%d\n",getpid());
	}
	return 0;
}

CLC@Embed_Learn:~/process$ gcc demo5.c
CLC@Embed_Learn:~/process$ ./a.out 
before fork:pid = 43993
after fork:pid = 43993 //fork以后还是由父进程在做
this is father print  //父进程就执行完毕了
after fork:pid = 43994  //子进程在做
this is child ,child pid43994  //子进程打印

demo6.c

#include <stdio.h> 
#include <sys/types.h>
#include <unistd.h>

int main()
{
	pid_t pid;

	printf("father: id = %d\n",getpid());

	pid = fork();
	
	if(pid > 0){
		printf("this is father print ,father pid = %d\n",getpid());
	}else if(pid == 0){
		
		printf("this is child ,child pid = %d\n",getpid());
	}
	return 0;
}

CLC@Embed_Learn:~/process$ gcc demo6.c
CLC@Embed_Learn:~/process$ ./a.out 
father: id = 44331
this is father print ,father pid = 44331
this is child ,child pid = 44332

我不知道pid>0是父进程,但是9行和14行获得的getpid却是一样的,由此推断而来,继续demo6.1验证

demo6.1.c

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
	pid_t pid;
	pid_t pid2;
	pid_t retpid;

	pid = getpid();
	printf("before fork: pid = %d\n",pid);

	retpid = fork();

	pid2 = getpid();
	printf("after fork: pid = %d\n",pid2);

	if(pid == pid2){
		printf("this is father print: retpid = %d\n",retpid);
	}
	else{
		printf("this id child print: retpid = %d,child pid = %d\n",retpid,getpid());
	}

	return 0;
}

/*
before fork: pid = 5794
after fork: pid = 5794
this is father print: retpid = 5795
after fork: pid = 5795
this id child print: retpid = 0,child pid = 5795

第14行的fork()不是真正意义上的返回两次,retpid被拷贝了一份,一份给子进程,一份给父进程,在父进程打印的时候中retpid>0,并且等于子进程的id号;
如果retpid=0的话,是说明被分配给了子进程了,只有子进程打印的时候retpid才等于0。
*/

CLC@Embed_Learn:~/process$ gcc demo6.1.c
CLC@Embed_Learn:~/process$ ./a.out 
before fork: pid = 44293
after fork: pid = 44293
this is father print: retpid = 44294
after fork: pid = 44294
this id child print: retpid = 0,child pid = 44294

第14行的fork()不是真正意义上的返回两次,retpid被拷贝了一份,一份给子进程,一份给父进程,在父进程打印的时候中retpid>0,并且等于子进程的id号;
如果retpid=0的话,是说明被分配给了子进程了,只有子进程打印的时候retpid才等于0。

demo7.c

#include <stdio.h> 
#include <sys/types.h>
#include <unistd.h>

int main()
{
	pid_t pid;
	int data = 10;


	printf("father: id = %d\n",getpid());

	pid = fork();
	
	if(pid > 0){
		printf("this is father print\n");
	}else if(pid == 0){
		
		printf("this is child ,child pid = %d\n",getpid());
		//data = data +100;
	}

	printf("data = %d\n",data);
	return 0;
}

CLC@Embed_Learn:~/process$ gcc demo7.c
CLC@Embed_Learn:~/process$ ./a.out 
father: id = 44439
this is father print
data = 10
this is child ,child pid = 44440
data = 10 

#include <stdio.h> 
#include <sys/types.h>
#include <unistd.h>

int main()
{
	pid_t pid;
	int data = 10;


	printf("father: id = %d\n",getpid());

	pid = fork();
	
	if(pid > 0){
		printf("this is father print\n");
	}else if(pid == 0){
		
		printf("this is child ,child pid = %d\n",getpid());
		data = data +100;
	}

	printf("data = %d\n",data);
	return 0;
}

CLC@Embed_Learn:~/process$ gcc demo7.c
CLC@Embed_Learn:~/process$ ./a.out 
father: id = 44439
this is father print
data = 10
this is child ,child pid = 44440
data = 110

demo8.c

#include <stdio.h> 
#include <sys/types.h>
#include <unistd.h>

int main()
{
	pid_t pid;
	int data = 10;

	while(1){
		printf("please input a data\n");
		scanf("%d",&data);
	
		if(data == 1){
			pid = fork();

			if(pid > 0){
			
			}else if(pid == 0){
				while(1){
					printf("do net request,pid=%d\n",getpid());
					sleep(3);
				}
			}

		}else{
			printf("wait, do nothing\n");
		}
	}
	return 0;
}

CLC@Embed_Learn:~/process$ gcc demo8.c
CLC@Embed_Learn:~/process$ ./a.out 
please input a data
2
wait, do nothing
please input a data
1
please input a data
do net request,pid=44555
do net request,pid=44555
do net request,pid=44555

......

demo9.c

#include <stdio.h> 
#include <sys/types.h>
#include <unistd.h>

int main()
{
	pid_t pid;

	pid = fork();

	if(pid > 0){
		while(1){
			printf("this is father print,pid = %d\n",getpid());
			sleep(1);
		}
	}else if(pid == 0){
		
		while(1){
			printf("this is child print,pid = %d\n",getpid());
			sleep(1);
		}
	}

	return 0;
}

CLC@Embed_Learn:~/process$ gcc demo9.c
CLC@Embed_Learn:~/process$ ./a.out 
this is father print,pid = 38629
this is child print,pid = 38630
this is child print,pid = 38630
this is father print,pid = 38629

......

fork取决于进程的调度,父和子都早争夺cpu

demo10.c

#include <stdio.h> 
#include <sys/types.h>
#include <unistd.h>

int main()
{
	pid_t pid;

	pid = vfork();

	if(pid > 0){
		while(1){
			printf("this is father print,pid = %d\n",getpid());
			sleep(1);
		}
	}else if(pid == 0){
		
		while(1){
			printf("this is child print,pid = %d\n",getpid());
			sleep(1);
		}
	}


	return 0;

}


CLC@Embed_Learn:~/process$ gcc demo10.c
CLC@Embed_Learn:~/process$ ./a.out 
this is child print,pid = 44588
this is child print,pid = 44588
this is child print,pid = 44588

......

vfork都是子进程先执行

demo11.c 

#include <stdio.h> 
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
	pid_t pid;

	int cnt = 0;

	pid = vfork();

	if(pid > 0){
		while(1){
			
			printf("cnt = %d\n",cnt);
			printf("this is father print,pid = %d\n",getpid());
			sleep(1);
		}
	}else if(pid == 0){
		
		while(1){
			printf("this is child print,pid = %d\n",getpid());
			sleep(1);
			cnt++;
			if(cnt == 3){
				//break;
				exit(0);
			}
			
		}
	}
	return 0;

}

CLC@Embed_Learn:~/process$ gcc demo11.c
CLC@Embed_Learn:~/process$ ./a.out 
this is child print,pid = 3434
this is child print,pid = 3434
this is child print,pid = 3434
cnt = 3
this is father print,pid = 3433
cnt = 3
this is father print,pid = 3433
cnt = 3
this is father print,pid = 3433
cnt = 3

......

子进程运行3次后,在退出

demo12.c

#include <stdio.h> 
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
	pid_t pid;

	int cnt = 0;

	pid = vfork();

	if(pid > 0){
		while(1){
			
			printf("cnt = %d\n",cnt);
			printf("this is father print,pid = %d\n",getpid());
			sleep(1);
		}
	}else if(pid == 0){
		
		while(1){
			printf("this is child print,pid = %d\n",getpid());
			sleep(1);
			cnt++;
			if(cnt == 3){
				//break;
				exit(0);
			}
			
		}
	}


	return 0;

}

 CLC@Embed_Learn:~/process$ gcc demo12.c -o newpro
CLC@Embed_Learn:~/process$ ./newpro 
this is child print,pid = 3566
this is child print,pid = 3566
this is child print,pid = 3566
cnt = 3
this is father print,pid = 3565
cnt = 3
this is father print,pid = 3565
cnt = 3
...


使用vfork(),子进程退出状态不被收集,变成僵尸进程

CLC@Embed_Learn:~/process$ ps -aux|grep newpro
Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html
CLC       3565  0.0  0.0   4160   424 pts/1    S+   19:40   0:00 ./newpro
CLC       3566  0.0  0.0      0     0 pts/1    Z+   19:40   0:00 [newpro] <defunct>//子进程3566变成僵尸进程
CLC       3568  0.0  0.0  13588   940 pts/2    S+   19:40   0:00 grep --color=auto newpro

demo13.c

#include <stdio.h> 
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
	pid_t pid;

	int cnt = 0;

	pid = fork();

	if(pid > 0){
		while(1){
			
			printf("cnt = %d\n",cnt);
			printf("this is father print,pid = %d\n",getpid());
			sleep(1);
		}
	}else if(pid == 0){
		
		while(1){
			printf("this is child print,pid = %d\n",getpid());
			sleep(1);
			cnt++;
			if(cnt == 3){
				//break;
				exit(0);
			}
			
		}
	}


	return 0;

}


CLC@Embed_Learn:~/process$ gcc demo13.c -o newpro
CLC@Embed_Learn:~/process$ ./newpro 
cnt = 0
this is father print,pid = 3842
this is child print,pid = 3843
cnt = 0
this is child print,pid = 3843
this is father print,pid = 3842
this is child print,pid = 3843
cnt = 0
this is father print,pid = 3842
cnt = 0
this is father print,pid = 3842

......

使用fork(),子进程退出状态不被收集,变成僵尸进程

CLC@Embed_Learn:~/process$ ps -aux|grep newpro
Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html
CLC       3842  0.0  0.0   4160   352 pts/1    S+   19:52   0:00 ./newpro
CLC       3843  0.0  0.0      0     0 pts/1    Z+   19:52   0:00 [newpro] <defunct>//子进程3483变成了僵尸进程
CLC       3845  0.0  0.0  13592   940 pts/2    S+   19:52   0:00 grep --color=auto newpro

 demo14.c

#include <stdio.h> 
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
	pid_t pid;

	int cnt = 0;

	pid = fork();

	if(pid > 0){
		wait(NULL);
		while(1){
			
			printf("cnt = %d\n",cnt);
			printf("this is father print,pid = %d\n",getpid());
			sleep(1);
		}
	}else if(pid == 0){
		
		while(1){
			printf("this is child print,pid = %d\n",getpid());
			sleep(1);
			cnt++;
			if(cnt == 3){
				//break;
				exit(0);
			}
			
		}
	}


	return 0;

}

CLC@Embed_Learn:~/process$ gcc demo14.c
CLC@Embed_Learn:~/process$ ./a.out
使用wait(), 收集僵尸进程
this is child print,pid = 39352
this is child print,pid = 39352
this is child print,pid = 39352
cnt = 0
this is father print,pid = 39351
cnt = 0
this is father print,pid = 39351
cnt = 0
...

在下面中没有39352这个子进程,子进程不会变成僵尸进程

CLC@Embed_Learn:~$ ps -aux|grep a.out
Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html
CLC      39121  0.0  0.0   4160   428 pts/1    T    13:17   0:00 ./a.out
CLC      39122  0.0  0.0      0     0 pts/1    Z    13:17   0:00 [a.out] <defunct>
CLC      39249  0.0  0.0   4160   428 pts/1    T    13:18   0:00 ./a.out
CLC      39250  0.0  0.0      0     0 pts/1    Z    13:18   0:00 [a.out] <defunct>
CLC      39305  0.0  0.0   4160   352 pts/1    T    13:44   0:00 ./a.out
CLC      39306  0.0  0.0      0     0 pts/1    Z    13:44   0:00 [a.out] <defunct>
CLC      39337  0.0  0.0   4160   352 pts/1    T    13:48   0:00 ./a.out
CLC      39341  0.0  0.0   4160   348 pts/1    T    13:48   0:00 ./a.out
CLC      39351  0.0  0.0   4160   352 pts/1    S+   13:50   0:00 ./a.out
CLC      39354  0.0  0.0  13592   948 pts/2    S+   13:50   0:00 grep --color=auto a.out

demo15.c

#include <stdio.h> 
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
	pid_t pid;

	int cnt = 0;
	int status = 10;

	pid = fork();

	if(pid > 0){
		wait(&status);
		printf("child quit,child status = %d\n",WEXITSTATUS(status));
		wait(NULL);
		while(1){
			
			printf("cnt = %d\n",cnt);
			printf("this is father print,pid = %d\n",getpid());
			sleep(1);
		}
	}else if(pid == 0){
		
		while(1){
			printf("this is child print,pid = %d\n",getpid());
			sleep(1);
			cnt++;
			if(cnt == 3){
				//break;
				exit(3);
			}
			
		}
	}


	return 0;

}

CLC@Embed_Learn:~/process$ gcc demo15.c
CLC@Embed_Learn:~/process$ ./a.out 
this is child print,pid = 3879
this is child print,pid = 3879
this is child print,pid = 3879
child quit,child status = 3 //子进程退出的状态解析出来了
cnt = 0
this is father print,pid = 3878
cnt = 0
this is father print,pid = 3878
cnt = 0

demo16.c

#include <stdio.h> 
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
	pid_t pid;

	int cnt = 0;
	int status = 10;

	pid = fork();

	if(pid > 0){
//		wait(&status);
		waitpid(pid,&status,WNOHANG);
		printf("child quit,child status = %d\n",WEXITSTATUS(status));
		wait(NULL);
		while(1){
			
			printf("cnt = %d\n",cnt);
			printf("this is father print,pid = %d\n",getpid());
			sleep(1);
		}
	}else if(pid == 0){
		
		while(1){
			printf("this is child print,pid = %d\n",getpid());
			sleep(1);
			cnt++;
			if(cnt == 5){
				//break;
				exit(3);
			}
		}
	}


	return 0;

}

CLC@Embed_Learn:~/process$ gcc demo16.c
CLC@Embed_Learn:~/process$ ./a.out 
child quit,child status = 0
this is child print,pid = 4118
this is child print,pid = 4118
this is child print,pid = 4118
this is child print,pid = 4118
this is child print,pid = 4118
cnt = 0
this is father print,pid = 4117
cnt = 0
this is father print,pid = 4117
cnt = 0

.......

waitpid以非阻塞的方式,CLC@Embed_Learn:~$ ps -aux|grep a.out,子进程还是会变成僵尸进程

demo17.c

#include <stdio.h> 
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
	pid_t pid;

	int cnt = 0;
	//int status = 10;

	pid = fork();

	if(pid > 0){
			printf("this is father print,pid = %d\n",getpid());

	}else if(pid == 0){
		
		while(1){
			printf("this is child print,pid = %d,my father pid = %d\n",getpid(),getppid());
			sleep(1);
			cnt++;
			if(cnt == 5){
				//break;
				exit(3);
			}
		}
	}


	return 0;

}

CLC@Embed_Learn:~/process$ gcc demo17.c -o guer
CLC@Embed_Learn:~/process$ ./guer 
this is father print,pid = 4182
CLC@Embed_Learn:~/process$ this is child print,pid = 4183,my father pid = 1
this is child print,pid = 4183,my father pid = 1
this is child print,pid = 4183,my father pid = 1
this is child print,pid = 4183,my father pid = 1
this is child print,pid = 4183,my father pid = 1

Linux避免系统存在过多孤儿进程,init进程收留孤儿进程,变成孤儿进程的父进程

Pid=1:init进程,作用—系统初始化

CLC@Embed_Learn:~/process$ ps -aux|grep guer
Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html
CLC       4183  0.0  0.0   4160    84 pts/1    S    22:56   0:00 ./guer
CLC       4185  0.0  0.0  13588   940 pts/2    S+   22:56   0:00 grep --color=auto guer

demo18.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);

int main(void)
{
    printf("before execl\n");
    if(execl("./echoarg","echoarg","abc",NULL) == -1)
    {
        printf("execl failed!\n");      

	perror("why: ");
    }
    printf("after execl\n");
    return 0;
}

echoarg.c 

#include <stdio.h>

int main(int argc,char *argv[])
{
    int i = 0;
    for(i = 0; i < argc; i++)
    {
        printf("argv[%d]: %s\n",i,argv[i]);
    }
    return 0;
}

CLC@Embed_Learn:~/process$ gcc demo18.c
CLC@Embed_Learn:~/process$ ./a.out 
before execl
argv[0]: echoarg
argv[1]: abc

demo19.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);

int main(void)
{
    printf("before execl\n");
    if(execl("/bin/ls","ls",NULL,NULL) == -1)
    {
        printf("execl failed!\n");      

	perror("why: ");
    }
    printf("after execl\n");
    return 0;
}

CLC@Embed_Learn:~/process$ gcc demo19.c
CLC@Embed_Learn:~/process$ ./a.out 
before execl
a.out        demo13.c  demo1.c    demo26.c  demo3.c    demo9.c    newpro
changData   demo14.c  demo20.c    demo27.c  demo4.c    echoarg
config.txt  demo15.c  demo21.c    demo28.c  demo5.c    echoarg.c
damo17.c    demo16.c  demo22.c    demo29.c  demo6.1.c  forktest
demo10.c    demo17.c  demo23.c    demo2.c   demo6.c    guer
demo11.c    demo18.c  demo24.c    demo30.c  demo7.c    mydemo
demo12.c    demo19.c  demo25.c    demo31.c  demo8.c    new

demo20.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);

int main(void)
{
    printf("before execl\n");
    if(execl("/bin/ls","ls","-l",NULL) == -1)
    {
        printf("execl failed!\n");      

	perror("why: ");
    }
    printf("after execl\n");
    return 0;
}

CLC@Embed_Learn:~/process$ gcc demo20.c
CLC@Embed_Learn:~/process$ ./a.out 
before execl
total 232
-rwxr-xr-x 1 CLC book 8481 Aug 29 00:23 a.out
-rwxr-xr-x 1 CLC book 8785 Dec 17  2020 changData
-rw-r--r-- 1 CLC book   33 Apr 11  2021 config.txt
-rw-r--r-- 1 CLC book    0 Nov 19  2020 damo17.c
-rw-r--r-- 1 CLC book  331 Nov 18  2020 demo10.c

......

-rwxr-xr-x 1 CLC book 8431 Dec 16  2020 mydemo
-rwxr-xr-x 1 CLC book 8640 Nov 18  2020 new
-rwxr-xr-x 1 CLC book 8583 Aug 28 19:52 newpro
 

demo21.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);

int main(void)
{
    printf("this is syetem time: \n");
    if(execl("/bin/date","date",NULL,NULL) == -1)
    {
        printf("execl failed!\n");      

	perror("why: ");
    }
    printf("after execl\n");
    return 0;
}

CLC@Embed_Learn:~/process$ gcc demo21.c
CLC@Embed_Learn:~/process$ ./a.out 
this is syetem time: 
Mon Aug 29 00:24:48 CST 2022

demo22.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);

int main(void)
{
    printf("before execl\n");
    if(execl("/bin/ps","ps","-l",NULL) == -1)
    {
        printf("execl failed!\n");      

	perror("why: ");
    }
    printf("after execl\n");
    return 0;
}

CLC@Embed_Learn:~/process$ gcc demo22.c
CLC@Embed_Learn:~/process$ ./a.out 
before execl
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S  1000  3110  3103  0  80   0 -  7002 wait   pts/1    00:00:00 bash
0 T  1000  3433  3110  0  80   0 -  1040 signal pts/1    00:00:00 a.out
1 Z  1000  3434  3433  0  80   0 -     0 exit   pts/1    00:00:00 a.ou <defunct>
0 T  1000  3448  3110  0  80   0 -  1040 signal pts/1    00:00:00 a.out
1 Z  1000  3449  3448  0  80   0 -     0 exit   pts/1    00:00:00 a.ou <defunct>
0 T  1000  3554  3110  0  80   0 -  1040 signal pts/1    00:00:00 a.out
1 Z  1000  3555  3554  0  80   0 -     0 exit   pts/1    00:00:00 a.ou <defunct>
0 T  1000  3565  3110  0  80   0 -  1040 signal pts/1    00:00:00 newpro
1 Z  1000  3566  3565  0  80   0 -     0 exit   pts/1    00:00:00 newp <defunct>
0 T  1000  3842  3110  0  80   0 -  1040 signal pts/1    00:00:00 newpro
1 Z  1000  3843  3842  0  80   0 -     0 exit   pts/1    00:00:00 newp <defunct>
0 T  1000  3878  3110  0  80   0 -  1040 signal pts/1    00:00:00 a.out
0 T  1000  3903  3110  0  80   0 -  1040 signal pts/1    00:00:00 a.out
0 T  1000  4068  3110  0  80   0 -  1040 signal pts/1    00:00:00 a.out
0 T  1000  4117  3110  0  80   0 -  1040 signal pts/1    00:00:00 a.out
0 R  1000  4408  3110  0  80   0 -  3482 -      pts/1    00:00:00 ps

demo23.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);

int main(void)
{
    printf("before execl\n");
    if(execlp("ps","ps","-l",NULL) == -1)
    {
        printf("execl failed!\n");      

	perror("why: ");
    }
    printf("after execl\n");
    return 0;
}

CLC@Embed_Learn:~/process$ gcc demo23.c
CLC@Embed_Learn:~/process$ ./a.out 
before execl
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S  1000  3110  3103  0  80   0 -  7002 wait   pts/1    00:00:00 bash
0 T  1000  3433  3110  0  80   0 -  1040 signal pts/1    00:00:00 a.out
1 Z  1000  3434  3433  0  80   0 -     0 exit   pts/1    00:00:00 a.out <defunct>
0 T  1000  3448  3110  0  80   0 -  1040 signal pts/1    00:00:00 a.out
1 Z  1000  3449  3448  0  80   0 -     0 exit   pts/1    00:00:00 a.out <defunct>
0 T  1000  3554  3110  0  80   0 -  1040 signal pts/1    00:00:00 a.out
1 Z  1000  3555  3554  0  80   0 -     0 exit   pts/1    00:00:00 a.out <defunct>
0 T  1000  3565  3110  0  80   0 -  1040 signal pts/1    00:00:00 newpro
1 Z  1000  3566  3565  0  80   0 -     0 exit   pts/1    00:00:00 newpro <defunct>
0 T  1000  3842  3110  0  80   0 -  1040 signal pts/1    00:00:00 newpro
1 Z  1000  3843  3842  0  80   0 -     0 exit   pts/1    00:00:00 newpro <defunct>
0 T  1000  3878  3110  0  80   0 -  1040 signal pts/1    00:00:00 a.out
0 T  1000  3903  3110  0  80   0 -  1040 signal pts/1    00:00:00 a.out
0 T  1000  4068  3110  0  80   0 -  1040 signal pts/1    00:00:00 a.out
0 T  1000  4117  3110  0  80   0 -  1040 signal pts/1    00:00:00 a.out
0 R  1000  4431  3110  0  80   0 -  3482 -      pts/1    00:00:00 ps

带p不需要加绝对路径

demo24.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);

int main(void)
{
    printf("before execl\n");


//	char *argv[] = {"ps","-l",NULL};
//    	if(execvp("ps",argv) == -1) 

    char *argv[] = {"ps",NULL,NULL}; //定义指针数组 多个指针
    if(execvp("ps",argv) == -1)
    {
        printf("execl failed!\n");      

	perror("why: ");
    }
    printf("after execl\n");
    return 0;
}

CLC@Embed_Learn:~/process$ gcc demo24.c
CLC@Embed_Learn:~/process$ ./a.out 
before execl
  PID TTY          TIME CMD
 3110 pts/1    00:00:00 bash
 3433 pts/1    00:00:00 a.out
 3434 pts/1    00:00:00 a.out <defunct>
 3448 pts/1    00:00:00 a.out
 3449 pts/1    00:00:00 a.out <defunct>
 3554 pts/1    00:00:00 a.out
 3555 pts/1    00:00:00 a.out <defunct>
 3565 pts/1    00:00:00 newpro
 3566 pts/1    00:00:00 newpro <defunct>
 3842 pts/1    00:00:00 newpro
 3843 pts/1    00:00:00 newpro <defunct>
 3878 pts/1    00:00:00 a.out
 3903 pts/1    00:00:00 a.out
 4068 pts/1    00:00:00 a.out
 4117 pts/1    00:00:00 a.out
 4442 pts/1    00:00:00 ps

demo25.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);

int main(void)
{
    printf("before execl\n");


//	char *argv[] = {"ps","-l",NULL};
//    	if(execvp("ps",argv) == -1) 

    char *argv[] = {"ps",NULL,NULL};
    if(execv("/bin/ps",argv) == -1)
    {
        printf("execl failed!\n");      

	perror("why: ");
    }
    printf("after execl\n");
    return 0;
}

CLC@Embed_Learn:~/process$ gcc demo25.c
CLC@Embed_Learn:~/process$ ./a.out 
before execl
  PID TTY          TIME CMD
 3110 pts/1    00:00:00 bash
 3433 pts/1    00:00:00 a.out
 3434 pts/1    00:00:00 a.out <defunct>
 3448 pts/1    00:00:00 a.out
 3449 pts/1    00:00:00 a.out <defunct>
 3554 pts/1    00:00:00 a.out
 3555 pts/1    00:00:00 a.out <defunct>
 3565 pts/1    00:00:00 newpro
 3566 pts/1    00:00:00 newpro <defunct>
 3842 pts/1    00:00:00 newpro
 3843 pts/1    00:00:00 newpro <defunct>
 3878 pts/1    00:00:00 a.out
 3903 pts/1    00:00:00 a.out
 4068 pts/1    00:00:00 a.out
 4117 pts/1    00:00:00 a.out
 4454 pts/1    00:00:00 ps 

demo26.c

#include <stdio.h> 
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
	pid_t pid;
	int data = 10;

	while(1){
		printf("please input a data\n");
		scanf("%d",&data);
		if(data == 1){
			pid = fork();

			if(pid > 0){
				wait(NULL);
			}
			if(pid == 0){
				int fdSrc;

				char *readBuf = NULL;

				fdSrc = open("config.txt",O_RDWR);
				int size = lseek(fdSrc,0,SEEK_END);
				lseek(fdSrc,0,SEEK_SET);

				readBuf = (char *)malloc(sizeof(char)*size + 8);

				int n_read = read(fdSrc,readBuf,size);

				char *p = strstr(readBuf,"LENG=");
				if(p==NULL){
					printf("not found\n");
					exit(-1);
				}

				p = p+strlen("LENG=");
				*p = '5';
				
				lseek(fdSrc,0,SEEK_SET);

				int n_write = write(fdSrc,readBuf,strlen(readBuf));
				close(fdSrc);
				printf("success!!!");
				exit(0);
			}
		}else{
			printf("wait, do nothing\n");
		}
	}
	return 0;
}

config.txt 

PEED=5
LENG=3
SCORE=90
LEVEL=95

CLC@Embed_Learn:~/process$ gcc demo26.c
CLC@Embed_Learn:~/process$ ./a.out 
please input a data
1
success!!!please input a data
2
wait, do nothing
please input a data
3
wait, do nothing
 

CLC@Embed_Learn:~/process$ cat config.txt 
PEED=5
LENG=5
SCORE=90
LEVEL=95

demo27.c

#include <stdio.h> 
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

int main()
{
	pid_t pid;
	int data = 10;

	while(1){
		printf("please input a data\n");
		scanf("%d",&data);
		if(data == 1){
			pid = fork();

			if(pid > 0){
				wait(NULL);
			}
			if(pid == 0){
				execl("./changData","changData","config.txt",NULL);
			//	exit(0);  //zhe ge cheng xu yong  bu le 
				
			}
		}else{
			printf("wait, do nothing\n");
		}
	}
	return 0;
}

 config.txt

PEED=5
LENG=3
SCORE=90
LEVEL=95

CLC@Embed_Learn:~/process$ gcc demo27.c

CLC@Embed_Learn:~/process$ ./a.out 
please input a data
2
wait, do nothing
please input a data
1
please input a data
 

CLC@Embed_Learn:~/process$ cat config.txt 
PEED=5
LENG=5
SCORE=90
LEVEL=95

demo28.c

#include <stdio.h> 
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

int main()
{
	pid_t pid;
	int data = 10;

	while(1){
		printf("please input a data\n");
		scanf("%d",&data);
		if(data == 1){
			pid = fork();

			if(pid > 0){
				wait(NULL);
			}
			if(pid == 0){
				//execl("./changData","changData","config",NULL);
				//exit(0);  //zhe ge cheng xu yong  bu le 
				system("./changData config.txt ");
			}
		}else{
			printf("wait, do nothing\n");
		}
	}
	return 0;
}

 config.txt

PEED=5
LENG=3
SCORE=90
LEVEL=95

CLC@Embed_Learn:~/process$ gcc demo28.c

CLC@Embed_Learn:~/process$ ./a.out 
please input a data
2
wait, do nothing
please input a data
1
please input a data
 

CLC@Embed_Learn:~/process$ cat config.txt 
PEED=5
LENG=5
SCORE=90
LEVEL=95

demo29.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);

int main(void)
{
    printf("before execl\n");


//	char *argv[] = {"ps","-l",NULL};
//    	if(execvp("ps",argv) == -1) 

//    char *argv[] = {"ps",NULL,NULL};
    if(system("ps") == -1)
    {
        printf("execl failed!\n");      

	perror("why: ");
    }
    printf("after execl\n");
    return 0;
}

CLC@Embed_Learn:~/process$ gcc demo29.c
CLC@Embed_Learn:~/process$ ./a.out 
before execl
  PID TTY          TIME CMD
 3460 pts/2    00:00:00 bash
 4717 pts/2    00:00:00 a.out
 4718 pts/2    00:00:00 sh
 4719 pts/2    00:00:00 ps
after execl

 demo291.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);

int main(void)
{
    printf("before execl\n");


//	char *argv[] = {"psxxx","-l",NULL};
//    	if(execvp("ps",argv) == -1) 

//    char *argv[] = {"ps",NULL,NULL};
    if(system("ps") == -1)
    {
        printf("execl failed!\n");      

	perror("why: ");
    }
    printf("after execl\n");
    return 0;
}

CLC@Embed_Learn:~/process$ gcc demo291.c 
CLC@Embed_Learn:~/process$ ./a.out 
before execl
sh: 1: psxxx: not found
after execl

等价于

CLC@Embed_Learn:~/process$ sh -c ps112
sh: 1: ps112: not found
 

demo30.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);

int main(void)
{


	system("ps");
    	return 0;
}

CLC@Embed_Learn:~/process$ gcc demo30.c
CLC@Embed_Learn:~/process$ ./a.out 
  PID TTY          TIME CMD
 3460 pts/2    00:00:00 bash
 4808 pts/2    00:00:00 a.out
 4809 pts/2    00:00:00 sh
 4810 pts/2    00:00:00 ps 

demo31.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);

int main(void)
{
	char ret[1024] = {0};
	FILE *fp;

	fp = popen("ps","r");
//size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
	int nread = fread(ret,1,1024,fp);

	printf("read  %d byte,ret = %s\n",nread,ret);
	system("ps");
    return 0;
}

CLC@Embed_Learn:~/process$ gcc demo31.c
CLC@Embed_Learn:~/process$ ./a.out 
read  141 byte,ret =   PID TTY          TIME CMD
 3460 pts/2    00:00:00 bash
 4818 pts/2    00:00:00 a.out
 4819 pts/2    00:00:00 sh
 4820 pts/2    00:00:00 ps

  PID TTY          TIME CMD
 3460 pts/2    00:00:00 bash
 4818 pts/2    00:00:00 a.out
 4819 pts/2    00:00:00 sh <defunct>
 4821 pts/2    00:00:00 sh
 4822 pts/2    00:00:00 ps

如果我//printf,则不会输出在屏幕中,原先没有管结果的时候,它一股脑的往屏幕上打,现在我把该往屏幕上打的,全都捕获到字符数组中来。

popen的用法/好处:可以得到这个指令的运行结果,可以把结果存到字符串数组,也可以写在文件里。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值