1、execl函数
用于执行系统命令。int execl(path, "ls", "-l", NULL);
调用execl函数后,子进程的代码段会被替换。执行成功无返回。
execl("bin/ls","ls","-l",NULL); 命令的地址通过 which ls 查看。
也可以执行自己开发的二进制程序,
execl("./test","test",""hello,NULL); 多用于执行用户自定义的应用程序。
execlp搜索环境变量,不用带路径。多用于执行系统命令
杀死i僵尸进程:不能使用kill -9 杀死,收不到信号,需要杀死僵尸进程的父进程。
2、PCB概念
PCB (进程控制块):本质是一个task_struct结构体;
进程的上限 ulimit-a
进程描述信息:进程唯一的标识符pid、ppid;
进程的状态信息:
当前的进程状态;初始、就绪、运行、挂起、停止。
进程的优先级;
进程的首地址;
进程的各种计时和通信信息
进程的资源信息:
进程的现场保护信息:cpu寄存器。
3、进程状态切换
init是1号进程,是用户进程,还有一个0号的系统进程。
进程的创建:
创建新的PCB,
复制父进程的环境,
拷贝系统资源,
修改进程空间为就绪状态。
进程的销毁:
关闭软中断
回收资源
写记账信息到全局记账文本
向父进程发送软中断信号,并且修改进程状态信息。
终止进程的方法:
main函数执行完成,return
调用exit的c函数,底层调用_exit系统函数
调用abort函数,底层发送中断信号
发送中断信号
挂起状态不能直接回到运行态,必须经过初始化状态。
4、fork函数
fork函数会返回两次,子进程返回的pid为零,父进程返回子进程的pid。
父子进程共享代码空间,但是他们的数据空间是独立的。
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
main() { p
id_t pid;
printf("fork!");
pid=fork();
if (pid < 0)
printf("Error in fork!\n");
else if (pid == 0)
printf("I am the child process. The process id is %d\n",getpid());
else printf("I am the parent process. The process id is %d\n",getpid()); }
5、父子进程能否共享全局变量
不能,父子进程的用户空间是独立的,也就是数据空间独立,数据需要进程间通信。
6、ps与kill命令
ps 显示进程信息的命令
常用参数:
-A 显示所有进程(等价于-e)(utility)
-a 显示一个终端的所有进程,除了会话引线
-N 忽略选择。
-d 显示所有进程,但省略所有的会话引线(utility)
-x 显示没有控制终端的进程,同时显示各个命令的具体路径。dx不可合用。(utility)
-p pid 进程使用cpu的时间
-u uid or username 选择有效的用户id或者是用户名
-g gid or groupname 显示组的所有进程。
U username 显示该用户下的所有进程,且显示各个命令的详细路径。如:ps U zhang;(utility)
-f 全部列出,通常和其他选项联用。如:ps -fa or ps -fx and so on.
-l 长格式(有F,wchan,C 等字段)
-j 作业格式
-o 用户自定义格式。
v 以虚拟存储器格式显示
s 以信号格式显示
-m 显示所有的线程
-H 显示进程的层次(和其它的命令合用,如:ps -Ha)(utility)
e 命令之后显示环境(如:ps -d e; ps -a e)(utility)
h 不显示第一行
常见的命令组合:
显示所有进程信息
ps -A
显示指定用户的信息
ps -u root
显示所有进程信息,连同命令行
ps -ef
ps与grep常用组合用法,查找特定进程
ps -ef | grep ssh
将目前属于您自己这次登入的PID与相关信息列出来
ps -l
KILL:
Kill + 进程号
立即杀死进程 -9
7、孤儿进程与僵尸进程
当子进程已经销毁,但是父进程没有调用wait或者waitpid方法获取子进程状态,这时候的进程就是僵尸进程。
当父进程已经销毁,但是他的一个或者多个子进程还在运行,这时候就是孤儿进程,后续的工作由init进程进行处理。
8、子进程回收中的wait函数和waitPid函数
当子进程退出的时候,内核会向父进程SIGCHLD信号,子进程的退出是个异步事件(子进程可以在父进程运行的任何时刻终止)
--子进程退出时,内核将子进程置为僵尸状态,这个进程成为僵尸进程,它只保留最小的一些内核数据结构,以便父进程查询子进程的退出状态
--父进程查询子进程的退出状态可以用wait/waitpid函数
1). 如果其所有子进程都在运行,则该进程阻塞
2). 如果一个子进程已经终止,正等待父进程获取其终止状态,则取得该进程的终止状态立即返回
3). 如果它没有任何子进程,则立即出错返回。
#include <sys/wait.h>
int status;
pid_t wait (&statloc); // 子进程的退出状态 会被保存到这里输入参数中 -1:没有子进程 if(WIFEXITED(status)) {
// 正常退出
} else if(WIFSIGNALED(status)) { //
被信号杀死
}
pid_t waitpid (pid_t pid, int * statloc, int optins); // pid =-1 等待任意子进程 // opti0ns 可以设置为WNOHANG 表示为非阻塞。设置为0 表示为阻塞 int status; pid_t wait (pid, &statloc, 0);
在一个子进程终止以前,wait使其线程阻塞,而waitpid有一个设置可以不阻塞。