进程的基础
程序和进程的区别
程序是静态的,存放在磁盘上,是指令的集合。
进程是程序运行的实例。一盒程序运行一次产生一个进程。
每个进程都有自己的pid,每个进程都有自己的PCB。
进程是资源分配的基本单位。
在linux操作系统下,进程之间的关系是父子关系或兄弟关系。
所有的用户进程形成了一棵树
如何查看这棵树?
pstree
环境变量可以被继承 自定义不可以。
使用系统调用fork (2)创建新进程
查看进程的相关信息: ps -aux
进程的退出
1.return 和exit的区别
return 只是函数的返回
#include<stdlib.h>
void exit(int status);
exit(3) 是进程的结束。
在进程结束前,调用一些函数。需要将这些函数注册给进程。
on_exit (3)
0 成功
非0 错误
atexit (3)
进程资源的回收
在进程退出以后,父进程会回收子进程的资源。
使用wait(2) waitpid(2)系统调用回收子进程的资源。
如果父进程早于子进程结束,那么父进程的子进程的父亲就是init进程,这种进程称为孤儿进程。
pid_t waitpid(pid_t pid,int * status,int options);
举例验证:
补充:
1.同步 异步
事情A和事情B,如果必须先执行完事情A,然后执行事情B,那么说这两件事情同步
如果两个事情的执行先后不确定,那么是异步。
2.给指定进程发送信号:kill -信号编号 进程的pid
3.子进程已经终止,但是父进程还没有回收子进程的资源,这时候,子进程处于僵尸状态,称为僵尸进程。
在进程的虚拟地址空间里加载新的映像(image)
在子进程的虚拟地址空间里加载新的影像,需要使用系统提供的一个家族的函数。
execl (3 )
#include <unistd.h>
extern char **environ;
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 *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[], char *const envp[]);
execve(2)
#include <unistd.h>
int execve(const char *filename, char *const argv[],char *const envp[]);
相同的exec
l list
v vector
p PATH
e 环境变量
返回值:
成功 调用永远不返回
-1 错误 errno被设置
在子进程的虚拟地址空间加载新的映像 代码参见 exec.c
root@ubuntu:/home/liuwuzhou/start/uc# ps -o pid,ppid,pgrp,comm
PID PPID PGRP COMMAND
3449 3225 3449 su
3457 3449 3457 bash
7922 3457 7922 ps
execl 例子:
结果:
execlp 例子:
结果同上
execvp例子:
结果同上
补充:
类似:ls -l filename
char * const ps_argv[]={"ls","-l" ,"filbame",NULL};
bash 调用fork 产生子进程,在子进程地址空间加载新的映像 execvp(ps_argv[0],ps_argv);
bash 有内部命令和内部命令构成
外部命令和bash不是同一个可执行程序 内部命令式是bash本身的一部分。
如何查看一个命令是内部还是外部? type 命令
使用system(3) 启动新的可执行程序
#include <stdlib.h>
int system(const char *command);
功能:执行一个shell命令
参数:
command:
返回值:
-1 错误
返回command的退出状态码
system 和exec系列函数的区别
第一个为system的结果
第二个为exec的姐结果