“这是我参与8月更文挑战的第15天,活动详情查看:8月更文挑战”
进程
- 任务:目标结果
- 程序:是为了完成任务,编写的一段代码,是一个静态的。
进程的概念
进程是程序为了完成任务执行的一次过程,是一个动态的(动态创建,调度,执行和消亡的整个过程)。进程被称为**资源分配的最小单位,**因为每一个进程在启动初期,都会申请一个0-4G的虚拟空间。
这个空间分为两个部分,0-3G用户空间,3-4G是内核空间,0-3G是进程之间独有的空间。互不影响。3-4G属于多进程共享的空间(后续用于进程之间通讯使用),因为进程用户空间相互独立,互不影响所以安全性较高。还会申请一个PCB进程控制块 是一个结构体。task_struct 里面存储了所有进程的资源
如:PC程序计数器、堆栈、文件描述符、进程的状态 、进程号等等
操作系统启动时会自动创建3个进程:
- 0:负责引导系统启动,也会创建一个1号进程--》init进程
- 1:负责初始化硬件**,回收资源**
- 2:负责资源的分配,系统的调度
进程之间存在这个一种竞态。执行速度是不一定的,所以父子进程结束的快慢也是不一定。这里考虑单核和多核cpu吧。
进程的调度机制
时间片轮询,上下文切换
进程的状态
进程的标志
进程号(PID):linux分配的进程的编号,每个进程都不一样方便管理。
进程在结束时,会释放进程号的所有权。其他进程等待它释放一段时间后
分配,并不会结束后立马去分配出去。
进程相关的命令
1.pstree--以树形显示所有进程
如果加上 -p 参数会显示进程号
linux@ubuntu:~/test/test04$ pstree
systemd─┬─ModemManager───2*[{ModemManager}]
├─NetworkManager─┬─dhclient
│ └─2*[{NetworkManager}]
├─VGAuthService
├─accounts-daemon───2*[{accounts-daemon}]
linux@ubuntu:~/test/test04$ pstree -p
systemd(1)─┬─ModemManager(804)─┬─{ModemManager}(846)
│ └─{ModemManager}(854)
├─NetworkManager(852)─┬─dhclient(958)
│ ├─{NetworkManager}(912)
│ └─{NetworkManager}(916)
├─VGAuthService(1283)
├─accounts-daemon(812)─┬─{accounts-daemon}(826)
│ └─{accounts-daemon}(830)
2.ps -ef--主要查看父子进程关系
linux@ubuntu:~/test/test04$ ps -ef
UID PID PPID C STIME TTY TIME CMD
linux 2214 1581 0 09:07 ? 00:00:50 /usr/lib/gnome-terminal/
linux 2220 2214 0 09:07 pts/0 00:00:00 bash
linux 2317 2214 0 09:28 pts/1 00:00:00 bash
linux 2332 2317 0 09:30 pts/1 00:00:00 vi test.c
PID 进程ID PPID 父进程ID
3.ps aux--主要查看进程的状态
linux@ubuntu:~/test/test04$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.2 159996 9328 ? Ss 09:01 0:04 /sbin/in
root 2 0.0 0.0 0 0 ? S 09:01 0:00 [kthread
root 3 0.0 0.0 0 0 ? I< 09:01 0:00 [rcu_gp]
进程的状态:
R | 运行态 |
S | 休眠态 |
I(i的大写) | 空闲态 |
T | 停止态 |
Z | 僵尸态 |
< | 优先级高进程 |
N | 优先级低 |
l(L的小写) | 该进程中包含线程 |
+ | 前台进程 |
s | 会话首进程 |
4.ps -ajx--主要查看家族关系
linux@ubuntu:~/test/test04$ ps -ajx
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
0 1 1 1 ? -1 Ss 0 0:04 /sbin/init a
0 2 0 0 ? -1 S 0 0:00 [kthreadd]
.
.
.
2214 2220 2220 2220 pts/0 3812 Ss 1000 0:00 bash
2214 2317 2317 2317 pts/1 2332 Ss 1000 0:00 bash
2317 2332 2332 2317 pts/1 2332 S+ 1000 0:00 vi test.c
2 3637 0 0 ? -1 I 0 0:11 [kworker/0:1
2 3666 0 0 ? -1 I 0 0:00 [kworker/u25
2 3740 0 0 ? -1 I 0 0:00 [kworker/u25
2 3808 0 0 ? -1 I 0 0:00 [kworker/u25
2220 3812 3812 2220 pts/0 3812 R+ 1000 0:00 ps -ajx
PGID:进程组ID
SID :会话ID
会话
会话是为了完成一个任务,一个或多个进程组成的一个集合。会话中有三大部分
- 会话首进程:创建会话的进程
- 前台进程组:一个具有亲缘关系的前台进程的集合
- 多个后台进程组:可以不具备亲缘关系的多个进程的集合
📢注意:会话首进程管理整个会话,如果会话首进程结束,那么会话中的所有进程都会结束
5.top--CPU占有率
动态查看进程信息:主要查看进程cpu占有率
linux@ubuntu:~/test/test04$ top
top - 19:27:56 up 10:26, 1 user, load average: 0.02, 0.03, 0.00
任务: 327 total, 1 running, 258 sleeping, 0 stopped, 0 zombie
%Cpu(s): 4.5 us, 3.1 sy, 0.0 ni, 92.5 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 4001668 total, 1796372 free, 1312536 used, 892760 buff/cache
KiB Swap: 2097148 total, 2097148 free, 0 used. 2441892 avail Mem
进程 USER PR NI VIRT RES SHR � %CPU %MEM TIME+ COMMAND
1601 linux 20 0 393132 56328 32848 S 3.0 1.4 1:05.81 Xorg
1726 linux 20 0 3056316 205076 95484 S 3.0 5.1 1:37.78 gnome-shell
2214 linux 20 0 796560 57740 43144 S 2.0 1.4 0:54.16 gnome-termin+
3822 linux 20 0 51364 4156 3380 R 1.0 0.1 0:00.31 top
1204 root 20 0 194612 13644 11120 S 0.3 0.3 0:56.93 vmtoolsd
6.jobs--查看用户后台进程列表
- ctrl + z :会将前台运行的进程暂停保存到后台
- fg :会将后台暂停的进程恢复到前台去运行
- fg + %序列号 :将指定的后台暂停程序恢复到前台运行
- bg :会将后台暂停程序在后台运行
- bg + %序列号 :指定哪一个进程
- 可执行程序名 + & :将进程运行在后台
创建进程:fork
-
头文件:
#include <sys/types.h>
#include <unistd.h>
-
原型:
pid_t fork(void);
-
功能:创建一个子进程
-
参数:无
-
返回值:
成功:📌返回给父进程子进程的ID号,返回给子进程 0
失败返回-1;
📢fork:失败的条件只有一个,内存不够了。
-
代码:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, const char *argv[])
{
int fd = open("./1.txt",O_RDWR|O_CREAT,0666);
if (-1 ==fd)
{
perror("open");
return -1;
}
//创建一个子进程
pid_t pid = fork();//创建了一个子进程
if(-1 == pid)
{
perror("fork");
return -1;
}
//利用返回值的机制,来让父子进程分别干不同的事情
if(pid == 0)
{
//子进程
printf("我是子进程\n");
write(fd,"hello world",11);
}
else if(pid > 0){
//父进程
char buf[123] = {0};
sleep(1);
close(fd);
fd = open("./1.txt",O_RDONLY);
printf("我是父进程,我的子进程的ID号为%d\n",pid);
read(fd,buf,sizeof(buf));
printf("buf = %s\n",buf);
}
while(1);
return 0;
}
linux@ubuntu:~/test/test04$ ./a.out
我是子进程
我是父进程,我的子进程的ID号为3866
buf = hello world!
闹心的fork!
这里要注意第二个的linux@ubuntu:~/test/test04$
,linux机制规定了一点,作为子进程,必须让父进程帮它回收。父进程在运行时,bash解析器要比父进程晚一点,因为bash解析器是父进程的父进程,要等待父进程结束,回收父进程。
1.坑
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
printf("hello");
fork();
printf("world");
return 0;
}
//这里有坑,printf打印没有'\n',hello还在缓存区,子进程会把这个一同复制过去。
linux@ubuntu:~/test/test04$ ./a.out
helloworldlinux@ubuntu:~/test/test04$ helloworld
2.加上'\n'
int main(int argc, const char *argv[])
{
printf("hello\n");//加上'\n后'
fork();
printf("world");
return 0;
}
linux@ubuntu:~/test/test04$ ./a.out
hello
worldlinux@ubuntu:~/test/test04$ world
3.多个fork
int main(int argc, const char *argv[])
{
fork();
fork();
printf("hello\n");
printf("world");
return 0;
}
linux@ubuntu:~/test/test04$ ./a.out
hello
worldlinux@ubuntu:~/test/test04$ hello
worldhello
worldhello
world
int main(int argc, const char *argv[])
{
int i;
for(i=0;i<3;i++)
{
printf("hello world\n");
fork();//放在下面
}
return 0;
}
linux@ubuntu:~/test/test04$ ./a.out
hello world
hello world
hello world
linux@ubuntu:~/test/test04$ hello world
hello world
hello world
hello world
int main(int argc, const char *argv[])
{
int i;
for(i=0;i<3;i++)
{
fork();//放在上面
printf("hello world\n");
}
return 0;
}
linux@ubuntu:~/test/test04$ ./a.out
hello world
hello world
hello world
linux@ubuntu:~/test/test04$ hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
4.查看父子关系
int main(int argc, const char *argv[])
{
printf("hello\n");
fork();
printf("world");
while(1);
return 0;
}
另开一个终端
linux@ubuntu:~$ ps aux
linux 4070 48.2 0.0 4504 744 pts/0 R+ 19:59 0:03 ./a.out
linux 4071 48.2 0.0 4504 80 pts/0 R+ 19:59 0:03 ./a.out
linux@ubuntu:~$ ps -ef
linux 4083 2220 46 20:02 pts/0 00:00:05 ./a.out
linux 4084 4083 46 20:02 pts/0 00:00:05 ./a.out
写时拷贝
fork函数创建子进程时要复制父进程的资源,但是子进程并不一定会用到 这些资源,所以说采用一种方式:当创建完子进程以后,子进程先共享父进程的资源。如果双方有一方去修改内容,修改之前复制一份到子进程。这就叫做写时拷贝技术。
文件共享
如果在fork之间打开了一些文件,获取了一些文件描述符。那么fork之后父进程和子进程公用这些fork之前获取的文件描述符。那么在操作过程之中,有可能造成读写指针互相影响。
利用进程复制文件
📝练习:使用两个进程共同去完成复制一个文件,将一个文件拷贝到另一个文件中
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
//使用文件IO打开文件 ,获取文件的大小
int fd = open(argv[1],O_RDONLY);
if (-1 == fd)
{
perror("open");
return -1;
}
int fd1 = open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0666);
if (-1 == fd1 )
{
perror("open1");
return -1;
}
//获取文件大小利用偏移量
int len = lseek(fd,0,SEEK_END);
//需要一个从开头一个从中间,需要找到中间
len = len / 2;
//开始创建子进程
//子进程从中间开始读取,从中间开始写入
//父进程就从开头读取,从开头写入,到中间截至
pid_t pid = fork();
if(-1 == pid)
{
perror("fork");
return -1;
}
if (pid == 0 )
{
//子进程 ---》中间
close(fd);//避免再读取时对父进程读写指针造成影响
close(fd1);
fd = open(argv[1],O_RDONLY);
if (-1 == fd)
{
perror("open");
return -1;
}
fd1 = open(argv[2],O_WRONLY);
if( -1 == fd1)
{
perror("open1");
return -1;
}
//将被读文件的读写指针偏移到中间
lseek(fd,len,SEEK_SET);
//将被写入的文件的读写指针偏移到中间
lseek(fd1,len,SEEK_SET);
char buf[123] = {0};//接收读到的输入,写入数据时使用
ssize_t ret = 0;//来接手read 的返回值
while((ret = read(fd,buf,123)))
{
if( -1 == write(fd1,buf,ret))
{
perror("write");
return -1;
}
}
close(fd);
close(fd1);
exit(0);
}else if (pid > 0)
{
//父进程 ---》从开始
lseek(fd,0,SEEK_SET);
lseek(fd1,0,SEEK_SET);
char buf[123] = {0};
ssize_t ret = 0;
while(len)//以工作量为循环条件,每次减去已经读到的
{
if (len >= 123)
{
ret = read(fd,buf,123);
}else{
ret = read(fd,buf,len);
}
write(fd1,buf,ret);
len = len - ret;
}
}
获取进程ID接口
getpid:
-
功能:获取自己的进程ID
-
头文件:
#include <sys/types.h>
#include <unistd.h>
-
原型:
pid_t getpid(void)
-
参数:无
-
返回值:
成功返回自己的进程ID
无失败
getppid:
-
功能:获取父进程的进程ID
-
原型: pid_t getppid(void);
-
参数:无
-
返回值:
返回自己父进程的ID号
无失败
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
pid_t pid = fork();
if(-1 == pid)
{
perror("fork");
return -1;
}
if ( 0 == pid)
{
printf("我是子进程\n");
printf("我是子进程我的进程号为%d\n",getpid());
printf("我是子进程我的父进程进程号为%d\n",getppid());
}else if(pid > 0 )
{
printf("我是父进程\n");
printf("我是父进程,我的子进程的ID号为%d\n",pid);
sleep(1);
printf("我是父进程,我的进程ID号为%d\n",getpid());
printf("我是父进程,我的父进程的ID号为%d\n",getppid());
}
}
三个结束进程的函数
exit:
- 头文件:
#include <stdlib.h>
- 原型:
void exit(int status);
- 功能:结束一个进程,先释放缓冲区
- 参数:status :结束进程时的状态,同return 正常结束用0 非正常结束-1
- 返回值:无
_exit:
- 头文件: #include <unistd.h>
- 原型: void _exit(int status);
- 功能:结束一个进程,不会释放缓冲区直接结束
- 参数:status :结束进程时的状态,同return 正常结束用0 非正常结束-1
- 返回值:无
atexit:
-
头文件:
#include <stdlib.h>
-
原型:
int atexit(void (*function)(void));
-
功能: 注册一个进程结束后的运行函数 //当进程结束时会调用function这个函数
-
参数:指向返回值时void类型参数时void 的一个函数指针
-
返回值:
成功返回0
失败返回一个非0值
代码:
#include <stdio.h>
#include <stdlib.h>
//准备一个void fun(void) 的函数
void fun(void)
{
printf("hello wrold\n");
}
int main(int argc, const char *argv[])
{
//开始注册函数
atexit(fun);
sleep(3);
return 0;
}
孤儿进程:
父进程优先于子进程结束。子进程失去父亲之后,子进程会认为1号进程是自己的父进程。那么1号进程负责回收和管理子进程。如果说很多子进程都认为1号进程为他的父进程。1号进程的负担会很大,所以,我们在编写代码时尽量让父进回收完子进程资源之后在结束。孤儿进程是没有危害的。
僵尸进程:
子进程优先于父进程结束。子进程会认为该父进程会回收自己的资源。但是父进程一直在忙于自己的事情未曾去回收子进程资源,子进程资源就得不到回收,但是子进程的任务已经结束了。所以说子进程就变成了僵尸进程。僵尸进程是有危害的。
📢注意:以后在写fork时都需要回收子进程资源。
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
pid_t pid = fork();
if(-1 == pid)
{
perror("fork");
return -1;
}
if(pid == 0)
{
exit(0);//子进程结束父进程未结束,子进程变成了僵尸进程
}else if(pid > 0 )
{
while(1){
sleep(1);
}
}
return 0;
}
处理僵尸进程:
wait :
-
头文件:
#include <sys/types.h>
#include <sys/wait.h>
-
原型: pid_t wait(int *wstatus);
-
功能:阻塞等待回收任意一个子进程资源
-
参数:wstatus :进程结束的状态,一般不考虑进程结束的状态直接填写NULL 缺省模式,如果说想接收一下exit的返回的状态值,它会将exit返回的状态值放入wstatus地址中的8-15位的地方 。
linux@ubuntu:~/test/IO/test$ ./a.out 0x7ffd5b0d5090 linux@ubuntu:~/test/IO/test$ ./a.out 0x7ffeb92b3760 linux@ubuntu:~/test/IO/test$ ./a.out 0x7ffdb51c1c20 0x0000000
-
返回值:
成功会返回接收到的进程的ID号
失败会返回 -1;
-
注意:如果父进程调用wait来回收资源,那么会阻塞等待。会降低父进程的工作效率。
-
代码:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
pid_t pid = fork();
if(-1 == pid)
{
perror("fork");
return -1;
}
if(pid == 0)
{
sleep(5);
exit(0);//子进程结束父进程未结束,子进程变成了僵尸进程
}else if(pid > 0 )
{
//父进程中
printf("父进程运行\n");
printf("接受成功,接收到子进程的ID号为%d\n",wait(NULL));
}
return 0;
}
waitpid:
-
头文件:
#include <sys/types.h>
#include <sys/wait.h>
-
原型:
pid_t waitpid(pid_t pid, int *wstatus, int options);
-
功能:回收子进程资源,可以不阻塞回收也可以指定回收哪一个。
-
参数:
- pid > 0 :回收指定的子进程
- pid == -1;回收任意一个子进程 如果采用阻塞的方式与wait一样
- pid == 0 时:回收同进程组中的任意一个子进程
- pid < -1 时:回收同进程组中ID号等于pid绝对值的子进程 注意:-号代表同组,对pid进行取绝对值,|pid|==正数
- wstatus :回收到的子进程结束时返回的状态
- options :操作方式
- 0:阻塞回收
- WNOHANG :非阻塞方式回收 如果去回收时,没有子进程结束,立马返回,如果说已经有 子进程结束了立马回收。
-
返回值:
成功返回回收到的子进程的ID号
失败返回-1;
-
如果: WNOHANG 非阻塞方式去回收时,子进程如果没有结束则返回0
使用最多还是 waitpid(-1;NULL;WNOHANG);
-
注意:需要频繁去调用函数去查看子进程结束与否
-
代码:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include<stdlib.h>
int main(int argc, const char *argv[])
{
pid_t pid = fork();
if(-1 == pid)
{
perror("fork");
return -1;
}
if(pid == 0) //子进程
{
sleep(5);
exit(0);//子进程结束父进程未结束,子进程变成了僵尸进程
}else if(pid > 0 )//父进程
{
pid_t pid1 = 0;
while(1)
{
printf("父进程在干自己的事情\n");
if( 0 < (pid1 = waitpid(-1,NULL,WNOHANG)))
{
printf("回收到了子进程资源,子进程的ID号为%d\n",pid1);
}
sleep(1);
}
}
return 0;
}
守护进程
是一种特殊的进程机制,默默的对我的工作进行服务的进程。是一个后台进程。init进程就是一个守护进程。后台进程:只允许向终端写入数据,不允许向终端读取数据。如果一旦对终端输入进行获取,那么就会立即终止后台进程。要脱离终端的管理,脱离会话的管理。守护进程一般用于例如:服务器、http、tftp、ftp
附加:ctrl +c 给前台的所有进程发一个终止的信号(如果父进程结束了,子进程被1号进程收养了,变成孤儿进程,那么ctrl+c就和子进程没有关系了)这时候就只能用kill
创建守护进程是有固定步骤的
-
变成孤儿进程。()kill:给进程发一个信号
-
创建一个新的会话,变成会话首进程 setsid
头文件:
#include <sys/types.h>
#include <unistd.h>
原型:
pid_t setsid(void);
功能:创建一个新的会话,并且创建者称为会话的首进程
参数:无
返回值:成功返回一个新的会话ID 失败返回-1
-
修改默认工作目录文件 chdir
头文件:#include <unistd.h>
原型:int chdir(const char *path);
功能:修改工作路径
返回值:成功返回0 失败返回-1
-
给与最高文件权限 umask
头文件:#include <sys/types.h> #include <sys/stat.h>
原型: mode_t umask(mode_t mask);
参数:想要修改的掩码值
返回值:一定会成功返回修改完毕的掩码值
-
关闭文件描述符 close(0)(0代表终端);注意如果说也不会对终端进行操作,请关闭所有文件描述符
-
开始做守护事件 ,如日志文件的写入
-
附加:getdtablesize
功能:计算该进程的文件描述符的个数
头文件:#include <unistd.h>
原型:int getdtablesize(void);
参数:无
返回值:成功返回文件描述符的个数
-
代码:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
//创建一个孤儿进程
pid_t pid = fork();
if(-1 == pid)
{
perror("fork");
return -1;
}
if(0 == pid)
{
//子进程
//创建一个会话,自己成为自己的主人
if(-1 ==setsid())
{
perror("setsid");
return -1;
}
//修改工作目录
if(-1 == chdir("/"))
{
perror("chdir");
return -1;
}
//修改文件掩码
umask(0);
//关闭文件描述符
close(0);
close(1);
close(2);
FILE * fp = fopen("./1.txt","a");
while(1)
{
//写日志文件
fprintf(fp,"Hello world\n");
fflush(fp);
sleep(1);
}
}
//不去管父进程,父进程自动结束
return 0;
}
EXEC族
一些函数的集合。该进程集合中的,所有的函数都是完成一个功能,只是函数用法不同而已。实现的功能为:用其他进程替换该进程,避免空间重新释放和申请
system :功能:在进程中调用其他进程
execl
-
原型:
int execl(const char *path, const char *arg, ... /* (char *) NULL */);
-
参数:
path :可执行文件的路径
arg : 给可执行文件传的参数
可以是多个参数:固定规则: "可执行文件的名字" ,"参数1" ,"参数2" .。。,NULL结尾
-
返回值:
如果执行成功的话,不做返回
如果失败返回 -1
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
pid_t pid = fork();
if(-1 == pid)
{
perror("fork");
return -1;
}
if(0 == pid)
{
printf("子进程在做自己的事情\n");
sleep(3);
printf("子进程任务结束\n");
//替换其他进程继续使用该空间--ls
if(execl("/bin/ls","ls","-l",NULL) == -1)
{
perror("execl");
return -1;
}
printf("子进程在做自己的事情\n");
//这条语句不会打印,因为子进程被替换掉了
}
else if(pid > 0)
{
//wait
wait(NULL);
}
return 0;
}
linux@ubuntu:~/demo/test/IO/test$ ./a.out
子进程在做自己的事情
子进程任务结束
总用量 655728
-rwxrwxrwx 1 linux linux 671444992 8月 26 17:47 1.txt
-rwxr-xr-x 1 linux linux 8512 8月 27 07:44 a.out
-rwxrwxrwx 1 linux linux 724 8月 27 07:44 test.c
execlp
-
原型:
int execlp(const char *file, const char *arg, ... /* (char *) NULL */);
-
功能不同点:只能调用PATH环境变量中的可执行文件
-
参数:
file :可执行文件的名字
arg : 给可执行文件传的参数
可以是多个参数:固定规则: "可执行文件的名字" ,"参数1" ,"参数2" .。。,NULL结尾
-
返回值:
如果执行成功的话,不做返回
如果失败返回 -1
-
代码
execv
-
原型:
int execv(const char *path, char *const argv[]);
-
参数:
path:目标的路径名称
arg : 给可执行文件传的参数
可以是多个参数:固定规则: {"可执行文件的名字" ,"参数1" ,"参数2" ,NULL }结尾
-
返回值:
如果执行成功的话,不做返回
如果失败返回 -1
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
pid_t pid = fork();
if(-1 == pid)
{
perror("fork");
return -1;
}
if(0 == pid)
{
printf("子进程在做自己的事情\n");
sleep(3);
printf("子进程任务结束\n");
//替换其他进程继续使用该空间--ls
/* if(execl("/bin/ls","ls","-l",NULL) == -1)//execl
{
perror("execl");
return -1;
}*/
/*if(execlp("ls","ls","-l",NULL) == -1)//execlp
{
perror("execlp");
return -1;
}*
char * arg[] ={"ls","-l",NULL} ;//execv
if(execv("/bin/ls",arg) == -1)
{
perror("execl");
return -1;
}
printf("子进程在做自己的事情\n");
//这条语句不会打印,因为子进程被替换掉了
}
else if(pid > 0)
{
//wait
wait(NULL);
}
return 0;
}