程序:
有序的指令集合
静态
进程:
程序的一次执行过程,包含创建、运行、结束
是系统分配资源的最小单位
进程的组成:
正文段
来自程序的代码段,指令
用户数据段
来自于程序的数据段,.data(全局变量,常量) .bass(未初始化的全局变量)
系统数据段
堆栈(栈空间数据)局部变量,形参,函数返回值
寄存器
PCB进程控制块
进程ID
优先级
进程的用户
进程的分类:
交互类进程
前台进程(可以由终端输入或输出的进程)
后台进程(只能对终端输出)
批处理进程
不属于某个终端,只是将进程提交到某个队列以便顺序执行
守护进程
由操作系统启动便开始运行的进程,操作系统关闭则终止
进程的状态:
运行态
运行态:拥有cpu
就绪态:准备运行
等待态
可中断:有资源可回到运行态
不可中断:有资源不一定回到运行态,需要特殊条件
停止态
暂停在后台(前台ctrl+z停止)
僵尸态
进程结束,其资源还未回收
死亡态
进程完全结束
进程的调度:
ps:
ps -aus:查看进程详细信息
stat:进程状态
S:等待态
s:拥有子进程的进程
I(大写i):闲置在内核中的进程
N:低优先级进程
<:高优先级进程
l(小写L):拥有子线程的进程
+:运行在前台的进程
R:运行态
T:停止态
Z:僵尸态
top:
NI:优先级(-20 - 19,高-低)
nice:
-n 5 ./a.out(运行时按5优先级运行)
renice:
-n 10 PID(修改此进程优先级)
kill:向指定进程发送信号
-l:查看所有信号(共62个)
-9:杀死进程
-19:暂停进程
bg:将停止的状态运行到后台
+ 任务号
+ % PID
fg:将停止的状态运行到前台
+ 任务号
+ % PID
进程的模式(执行模式):
用户模式
内核模式
进程相关的系统调用:
#include <unistd.h>
pid_t fork(void);
功能:创建子进程
返回值:成功将子进程PID返回父进程中,将0返回到子进程中,失败返回-1到父进程
子进程会拷贝父进程几乎所有内容
父子进程运行区别:
父进程从main开始运行
子进程从fork(父节点当前状态)开始运行
父子进程参与统一调度,运行顺序是不一定的
一般而言子进程结束都由父进程回收资源
如果父进程先结束,子进程的资源由其他进程回收
#include <sys/types.h>
#include <unistd.h>
pid_t vfork(void);
功能:创建子进程
返回值:成功将子进程PID返回父进程中,将0返回到子进程中,失败返回-1到父进程
区别:vfork子进程结束后父进程才开始执行,而fork顺序不一定
#include <unistd.h>
pid_t getpid(void);//获得当前进程PID
pid_t getppid(void);//获得父进程PID
exec函数族(进程内容替换,运行其他可执行文件,PID不会变)
#include <unistd.h>
extern char **environ;
int execl(const char *pathname, const char *arg, .../* (char *) NULL */);
int execlp(const char *file, const char *arg, .../* (char *) NULL */);
int execle(const char *pathname, const char *arg, ... /*, (char *) NULL, char *const envp[] */);
int execv(const char *pathname, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[], char *const envp[]);
pathname:路径名
file:文件名(execlp与execvp是以系统环境变量为运行的地址,可执行文件需在bin中)
arg:命令及其参数(“命令”,“参数”)
NULL:结尾
envp:存储环境变量的指针数组
l:以列表的形式
v:以容器的形式
运行错误返回-1
#include <stdlib.h>
void exit(int status);
功能:当前进程退出
status:进程退出时的状态值,0为正常结束
#include <unistd.h>
void _exit(int status);
功能:当前进程退出
status:进程退出时的状态值,0为正常结束
区别:标准库调用和系统调用
_exit在结束进程时不会刷新缓冲区内容,而exit会刷新缓冲区
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *wstatus);
功能:进程阻塞等待子进程结束
返回值:成功返回退出子进程的PID,失败返回-1
wstatus:获取子进程退出的状态值
查看进程退出状态值的宏函数
WEXITSTATUS(wstatus)//等同((wstatus >> 8) & 0xff,返回子进程exit中的值)
查看进程是否正常退出
WIFEXITED(wstatus)//等同(wstatus & 0x7f,若正常退出,为0;若异常退出,返回相应异常信号)
pid_t waitpid(pid_t pid, int *wstatus, int options);
功能:处理子进程
返回值:成功option为0时,返回退出的子进程pid;option为WNOHANG,没有子进程返回0,有则返回PID。失败返回-1
pid:>0等待指定进程pid,-1等待任意子进程退出,<-1等待其组ID等于pid的绝对值的任一子进程,0等待其组ID等于pid的任一子进程
wstatus:获取子进程退出的状态值
option:0:阻塞等待进程结束,WNOHANG:非阻塞处理子进程退出(若没有子进程退出,会立即返回,若子进程退出则处理资源)
守护进程
在linux系统启动时就会开始运行的进程,当系统关闭时结束,实际工作为周期性完成某些特定操作
daemo守护进程:不属于某个终端,也是一个后台jinc
创建子进程,结束父进程,子进程将变为后台进程
摆脱终端,创建一个新的会话组,并使得该子进程成为该会话组的组长
#include <sys/types.h>
#include <unistd.h>
pid_t setsid(void);
返回值:成功为sid会话号,失败为-1
改变该进程的工作目录,建议修改为根目录
#include <unistd.h>
int chdir(const char *path);
path:文件夹路径
返回值:成功为0,失败为-1
重设文件掩码
#include <sys/types.h>
#include <sys/stat.h>
mode_t umask(mode_t mask);
mask:重设的掩码值
关闭所有以打开文件描述符
#include <unistd.h>
int getdtablesize(void);
返回值:当前的文件描述符的最大值
守护进程相关功能
由自己定义
部分代码示例
//fork 创建进程
#include <stdio.h>
#include <unistd.h>
void fun01()
{
while(1)
{
printf("child process\n");
sleep(1);
}
}
void fun02()
{
while(1)
{
printf("parent process\n");
sleep(1);
}
}
int main(int argc, char *argv[])
{
int pid = fork();
if(pid<0)
{
perror("fork");
return -1;
}
if(pid==0)
{
fun01();
}else
{
fun02();
}
return 0;
}
//exec
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
printf("Run:\n");
execl("/bin/ls","ls","-l",NULL);
/*char *a[]={"ls",NULL};
execv("/bin/ls",a);*/
return 0;
}
//wait
#include <stdio.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
pid_t pid = fork();
if(pid==0)
{
printf("Im child pid=%d\n",getpid());
sleep(1);
exit(10);
}
else
{
int status;
int cpid=wait(&status);
printf("Im parent cpid=%d status=%d\n",cpid,WEXITSTATUS(status));
}
return 0;
}
//waitpid
#include <stdio.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
pid_t pid = fork();
if(pid==0)
{
sleep(1);
printf("Im child\n");
exit(10);
}
else
{
int status;
int cpid=waitpid(-1,&status,0);
printf("Im parent cpid=%d status=%d",cpid,WEXITSTATUS(status));
}
return 0;
}
//创建守护进程
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
//创建子进程,并让它成为后台进程
pid_t pid = fork();
if(-1 == pid)
{
perror("fork is fail");
exit(-1);
}
else if(0 == pid)
{
//创建会话组,并成为会话组组长
pid_t sid = setsid();
if(-1 == sid)
{
perror("sid is fail");
exit(-1);
}
//修改工作目录
int ret = chdir("/");
if(-1 == ret)
{
perror("chdir is fail");
exit(-1);
}
//修改文件掩码
umask(0);
//关闭所有以打开的文件描述符
int num = getdtablesize();
for(int i = 0;i<num;i++)
{
close(i);
}
//守护进程功能
FILE *fp = fopen("/home/hqyj/zz/process/1.txt","r+");
while(1)
{
sleep(1);
time_t m_time = time(NULL);
struct tm *p = localtime(&m_time);
char buf[1024]={0};
sprintf(buf,"%d/%d/%d %d:%d:%d\n",p->tm_year+1900,p->tm_mon+1,p->tm_mday,p->tm_hour,p->tm_min,p->tm_sec);
fwrite(buf,sizeof(buf),1,fp);
}
}
}