前言
前面讲了链接等,第八章讲进程
一、进程
我个人理解的是在ubuntu上打开终端,执行一个程序,然后再打开一个终端,执行另一个程序,这种不同终端执行的不同程序就是进程
而如果同时运行三个进程就是同时控制流同时跑三个进程,先执行一会A,再执行一会B,在执行一会C,然后又执行一会A,这种情况称为上下文切换
不同的进程由不同的pid进行表示,pid的数据类型是pid_t
流如果有重叠执行的时间,就称为并发
在linux系统中,可以用ps -aux
查看pid
关于进程有以下几个常用函数及其用法
创建进程
fork():创建一个子进程,返回两次,一次给父进程,返回子进程的pid,另一个给子进程中返回0
“杀死进程”
exit():退出当前进程
回收进程(收尸)
waitpid():等待退出的进程,去回收他们,函数原型:waitpid(pid_t pid, int* statusp,int option),waitpid返回已终止进程的pid
关于status的宏
WIFEXITED(status):调用了exit就为1,否则为0
WEXITSTATUS(status):返回的是子进程退出状态
当pid在程序里面等于0时就是调度进程,实现进程的切换,个人感觉就和C里面的main一样,一直运行(可能比喻不太恰当)。pid = 0还有一种情况,就是在子进程中fork的返回值
pid=1的进程是init进程,实际上就是父进程
int main()
{
int status;
pid_t pid;
printf("Hello\n");
pid = Fork();
printf("%d\n",!pid);
if(pid != 0)
{
if(waitpid(-1,&status,0)>0)
{
if(WIFEXITED(status)=0)
{
printf("%d\n",WEXITSTATUS(status));
}
}
}
printf("Bye\n");
exit(2);
}
进程图如图所示
sleep:进程休眠函数:参数是请求的时间,返回请求时间下还需要sleep的秒数。
二、加载并运行程序
exevce:执行函数
execve(const char* filename,const char* argv[],const char* envp[]);
参数和环境变量形式类似于数组,argv是指针数组,以null结尾
所以,main函数的三个参数argc就是argv[]的非空个数,argv就是argv[]中的第一个条目,envp就是envp[]的第一个条目
运行程序时,先调用parseline函数,这个函数主要是对命令行参数解析,给到execve函数的arg[],如果是内置shell命令,会优先执行
然后调用builtin_command函数,检查第一个参数是不是shell命令(quit),如果是就返回1,不是,就返回0,那么shell创建一个子进程,并在子进程中执行所请求的程序,然后使用waitpid函数等待终止
三、信号
信号就是一条小消息,信号的发射机制和进程组相关
进程组
每个进程只属于一个进程组,,每一个进程组有pid_t类型来表示,一个子进程和一个父进程同属于一个进程组,用getpgrp函数和setpgid函数可以改变自己或者其他进程组的pid
用/bin/kill程序可以向另外的进程发送信号/bin/kill -9 15213
发送信号9给进程15213,如果是/bin/kill -9 -15213
会发送到pid里面的每一个进程
alarm函数
给自己发信号,alarm(secs)在secs秒后发送一个sigalrm信号给进程
sighandler_t signal(int signum, sighandler_t handler);
开始获取信号值为signum的信号,如果获取到该信号,则开始执行handler指向的函数,成功返回原本的信号处理函数指针,失败返回 SIGERR,
如果handle是SIG_IGN忽略这个信号,如果是SIG_DFL就默认处理
SIGERR的宏为 #define SIG_IGN ((sighandler_t)-1)
pause函数:
1.函数原型:
int pause(void);
2.功能解释:
暂停进程,把当前进程置成就绪态,让出CPU,直到收到任意一个信号后终止,并且当处理完该信号之后,直接执行pause()函数下面的语句
3.返回值:
只返回-1
4.参数解释:
不需要传参,如:pause();printf(“pause over\n”);//当前进程暂停,直到系统任意发出一个信号,pause()才被终止(打断),开始继续执行printf()。
四、非本地跳转
就是从一个函数转到另一个正在执行的函数,而不需要call和ret,通过setjump()函数和longjump()函数实现
setjump:就是保存现在的调用环境,方便后面恢复
longjump:从缓冲区中恢复环境,,然后setjump返回
而sigsetjump和siglongjump处理的则是信号处理的版本