进程与程序
进程的分类:
查看进程
ps
,显示出当前用户有终端控制权的进程信息ps -aux
,以列表形式显示详细信息
a
所有用户的终端控制进程x
所有用户的无终端控制的进程u
详细方式显示进程的详细信息列表
USER
进程的用户PID
进程的id%CPU
进程的cpu使用率%MEM
内存的使用率VSZ
占用虚拟内存的大小RSS
占用物理内存的大小TTY
终端的次设备号,如果无终端控制显示?STAT
进程的状态
O
就绪态,等待被系统调度R
运行态,Linux无就绪态,归于RS
休眠态,可以被系统中断(信号)唤醒转入运行态T
暂停态,是被SIGSTOP信号暂停,由SIGCONT信号转入运行态Z
僵尸态,已经结束停止运行,但父进程还没有回收<
高优先级进程N
低优先级进程l
多线程化的进程+
在前台进程组中的进程s
会话首进程START TIME
进程的开始时间COMMAND
程序可执行文件名父进程与子进程,孤儿进程与僵尸进程
一个进程A可以创建出另一个进程B,创建者叫fu进程,被创建进程叫子进程,父进程启动子进程后,在操作系统的调用下父进程同时执行(同步)。
如果子进程先于父进程结束,会向父进程发送SIGCHLD信号,父进程收到信号后,就应该去回收子进程的相关资源,但在默认情况下,父进程忽略该信号
当子进程结束后,父进程没有回收子进程的资源,子进程变成了僵尸进程
如果父进程先于子进程结束,子进程就变成了孤儿进程,同时被孤儿院收养(init),然后就变成了init 的子进程
进程标识符
操作系统会为每个进程分配一个唯一的标识符,采用无符号整数表示,即进程ID
进程ID在任何时候都是唯一的,但是可以重用,当一进程结束,新创建的进程才可以使用它的进程ID(延时重用)
pid_t fork(void);
#include
#include
int main(){
pid_t id = fork();
if(id == 0){
//子进程分支
printf("我的子进程%u,我的父进程是%u\n",getpid(),getppid());
}else{
//父进程分支
printf("我是父进程%u,我的子进程是%u\n",getpid(),id);
}
}
int main(){
printf("*");
fork();
printf("*");
fork();
}
练习1 实现一个程序来验证子进程确实拷贝了父进程的数据段,bss段,堆,栈,IO流
homework
练习2 为一个父进程创建5个子进程,一共六个进程
homework
从main函数中return
调用标准库中的exit函数
void exit(int status);
先调用事先注册的函数(通过atexit/on_exit)
int on_exit(void (*function)(int , void *), void *arg);
int atexit(void (*function)(void));
#include
#include
#include
void onfunc(int num, void* arr){
printf("%s %d %s\n",__func__,num,(char*)arr);
}
void atfunc(void){
printf("我要死了。。\n");
}
int main(){
on_exit(onfunc,"silesile...");
atexit(atfunc);
exit(10);
}
冲刷所有处在未关闭状态的标准IO流,删除所有临时文件
返回一个整数(EXIT_SUCCESS/EXIT_FAILURE)给操作系统
该函数不会返回,它的功能借助了_exit/_Exit函数
调用_exit/_Exit
函数退出
#include
void _exit(int status);
#include
void _Exit(int status);//调用系统的_exit
进程结束前会关闭所有处于打开状态的文件描述符
把所有子进程托付给孤儿院(init)
向它的父进程发送SIGCHLD信号
注意 exit函数也执行以上操作,因此它底层调用了_exit/_Exit
进程的最后一个线程执行最后一条语句
进程的最后一个线程调用了pthread_exit函数
wait/waitpid
pid_t wait(int *wstatus);
pid_t waitpid(pid_t pid, int *wstatus, int options);
#include
#include
#include
void sigchld(int sig){
int status = 0;
pid_t id = wait(&status);//waitpid
printf("我的孩子%u,去世了...5555!!!,它的遗言是%d\n",id,WEXITSTATUS(status));
}
int main(){
signal(SIGCHLD,sigchld);
if(fork()){
printf("我是进程%u\n",getpid());
pasue();
}else{
sleep(3);
printf("我是进程%u\n",getpid());
return
}
}
vfork
pid_t vfork(void);
execl
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[]);
int main(){
pid_t id = vfork();
if(id){
printf("我是子进程%u,我的父进程是%u\n",getpid(),getppid());
execl("./a.out","a.out",NULL);
}else{
printf("我是父进程%u,我的子进程是%u",getpid(),id);
pause();
}
}
system
int system(const char *command);
#include
#include
int main(){
system("./a.out");
printf("我是父进程\n");
pause();
}
练习 实现system函数
homework
pid_t getpgid(pid_t pid);
int setpgid(pid_t pid, pid_t pgid);