进程相关知识点

本文详细介绍了进程的相关概念,包括进程与程序的区别、进程的三种状态以及进程ID。讲解了进程的创建、查看和终止,重点阐述了fork、wait、exit及进程收尸的方法。此外,还探讨了进程的执行,特别是exec族函数的应用。最后,讨论了守护进程的创建过程及其重要特性。通过示例代码展示了如何实现进程的各个操作。
摘要由CSDN通过智能技术生成

进程

目录

进程

一.进程的相关概念

二.进程的系统调用

三.进程的任务执行

四.进程的守护精灵


一.进程的相关概念

1.进程和程序有什么不同?

程序:是一个静态的概念。 它是一些保存在磁盘上的指令的有序集合,没有任何执行的概念,是数据 段、正文段。

进程:是一个动态的概念。是程序的执行过程和载体,是一个程序的一次执行的过程,是数据段、正文段、堆栈段。程序执行和资源分配的最小单位。

2.进程的状态

分别为:初始态 就绪态 执行态 阻塞态 结束态

(1)就绪状态:进程已获得除CPU外的所有必要资源,只等待CPU时的状态。一个系统会将多个处于就绪状态的进程排成一个就绪队列。

(2)执行状态:进程已获CPU,正在执行。单处理机系统中,处于执行状态的进程只一个;多处理机系统中,有多个处于执行状态的进程。

(3)阻塞状态:正在执行的进程由于某种原因而暂时无法继续执行,便放弃处理机而处于暂停状态,即进程执行受阻。(这种状态又称等待状态或封锁状态)

3.进程悲苦的一生

出生 --> fork --> 成家立业 exec --> 消亡

其中消亡又分为:a.自然消亡 b.自杀(return 0) c.他杀(kill)

不得不说确实悲苦,根据是父亲还是孩子的消亡又分为“僵尸进程”和“孤儿进程”

僵尸进程:父进程没消亡 但不为子进程收尸 子进程是僵尸进程 避免僵尸进程

孤儿进程:父进程消亡 子进程还在运行 这时 子进程是孤儿进程 会被init进程领养并收尸

4.进程ID

init 进程是进程祖先,它的 PID1

ps aux 查看所有用户所有进程详细信息

pstree 查看进程树

top 动态查看进程信息

q 退出

二.进程的系统调用

1.进程的查看和创建

1.1获取进程的ID

#include <sys/types.h>
#include <unistd.h>
​
       pid_t getpid(void);//pid 是int别名 
       //功能:获取当前调用进程PID
       
       pid_t getppid(void);
       //功能:获取当前调用进程的父进程的PID

1.2  fork

#include <unistd.h>
​
       pid_t fork(void);
       功能:创建新进程
       返回值:成功调用返回两次 在父进程中返回子进程PID    在子进程中返回0
              出错返回-1

1.3咋区分两个进程

通过他们的返回值来进行区分

if(0==id)//说明在子进程中
{
    //子进程
    printf("子进程:%d  father:%d\n",getpid(),getppid());
}
else if(id>0)//说明在父进程中
{
    //父进程
    printf("父进程:%d  father:%d\n",getpid(),getppid());
}
 

1.4控制父子进程执行的顺序

父子进程执行的先后顺序不确定 取决于系统调度策略

比如我们可以通过sleep来控制进程执行的先后顺序

if(0==id)//说明在子进程中
{
    //子进程
    printf("子进程:%d  father:%d\n",getpid(),getppid());
}
else if(id>0)//说明在父进程中
{
    sleep(1);
    //父进程
    printf("父进程:%d  father:%d\n",getpid(),getppid());
}


​总结:
​
1.子进程复制父进程的数据空间 堆栈 代码段(共享正文段)
​
2.复制后 两个进程空间完全独立 子进程变量改变 父进程不会影响

2.进程的消亡

2.1进程的终止方式

有8种方式使进程终止,其中

有5种为正常终止,它们是

1:从 main 返回

2:调用 exit

3:调用 _exit 或 _Exit

4:最后一个线程从其启动例程返回

5:最后一个线程调用 pthread_exit

有3种为异常终止,它们是

6:调用 abort()

7:接到一个信号并终止

8:最后一个线程对取消请求做出响应

函数名: abort

功 能: 异常终止一个进程

用 法: void abort(void);

头文件:#include <stdlib.h>

说明: abort函数是一个比较严重的函数,当调用它时,会导致程序异常终止

2.2exit与_exit

exit 会刷新IO缓存

_exit 不刷新IO缓存

#include <stdlib.h>
​
       void exit(int status);
       //功能:结束进程 
    
​
#include <unistd.h>
​
       void _exit(int status);
       //功能:立即结束进程

3.进程的收尸

3.1 wait

 #include <sys/types.h>
 #include <sys/wait.h>
​
pid_t wait(int *status);//scanf()
    功能:等待一个子进程结束 取得子进程结束的状态 将其保存在status中
    返回值:返回被收尸的子进程PID 如果没有子进程返回-1
    
    注意: 
    a、父进程调用wait时 父进程会阻塞等待子进程结束
    b、如果父进程不关心子进程退出的状态  wait参数可以传NULL 就丢弃结束信息
    c、wait后 子进程占用的资源会被释放
    
    
    参数:status 如果为空 就丢弃结束信息
    WIFEXITED(status)   判断是否正常退出 真-->正常退出 假-->是异常退出
    WEXITSTATUS(status) 取得进程结束时的返回值
​
    WIFSIGNALED(status) 判断进程是否被信号终止 如果是 则返回真
    WTERMSIG(status)    判断是被哪个信号终止的

3.2 waitpid

#include <sys/types.h>
#include <sys/wait.h>
​
 pid_t waitpid(pid_t pid, int *status, int options);
      功能:收尸
      参数1:
            pid <-  1  等待其进程组组长ID(GID)等于pid的绝对值的任意子进程 
            pid == -1  该进程任意子进程
            pid >   0  进程ID为pid的进程  5678
            waitpid(-1,&sta,0)等价于wait(&sta)
​
    参数2 同wait
    参数3:
            0 等待子进程结束
           WNOHANG  不等待
​
    返回值:
         >0 被收尸的子进程的PID 
          0 参数3用WNOHANG 且没有子进程退出
         -1 出错

三.进程的任务执行

exec族函数:在本进程中加载另一个程序 并且从头开始执行 本进程会完全被新进程替换

注意:在执行完毕后 除了进程号没变以外 其他内容都被替换掉了

应用:

1)本进程重生

2)通过fork创建新进程 让新进程执行其他任务—主要应用

1. execl

#include <unistd.h>
 int execl(const char *path, const char *arg, ...);
格式:execl(可执行文件的路径,可执行文件名称,参数1,参数2,参数3,….,NULL)
注意:可执行文件路径 必须是which结果  which ls

2. execvp

#include <unistd.h>
 int execvp(const char *file, char *const argv[]);
格式:execvp(可执行文件名,指针数组);

四.进程的守护精灵

1.相关的概念

前台进程:依附终端 终端结束 进程结束

后台进程:不依附终端 自己独立存在

进程组: 多个进程

会话: 多个进程组

2.创建守护进程

1).创建子进程 父进程结束(init领养子进程)

2).创建新会话 setsid()---彻底脱离终端

3).改变当前工作目录 chdir("/tmp")

4).修改文件掩码

掩码:掩掉权限 umask(0)

5).关闭所有打开的文件描述符

int getdtablesize(void);//获取当前进程打开的文件总个数

int n=getdtablesize();

for(i=0;i<n;i++)

{

close(i);

}

实例

#include <time.h>
​
void mydaenon()
{
    //1.创建子进程  父进程退出
    pid_t id = fork();
    if(id>0)
    {
        exit(-1);
    }
    
    //只剩下子进程
    //2.创建会话
    setsid();
    
    //3.改变当前工作目录
    chdir("/tmp");
    
    //4.修改文件掩码
    umask(0);
    
    //5.关闭所有打开的文件描述符号
    int n=gettablesize();
    int i;
    for(i=0;i<n;i++)
    {
        close();
    }
}
​
int main()
{
    //创建守护进程
    mydaemon();
    
    //守护进程任务
    time_t t;
    FILE *fp = fopen("time.log","a");
    while(1)
    {
        //将系统时间写入日志文件
        t = time(NULL);
        fprintf(fp,"%s",ctime(&t));
        fflush(fp);
        sleep(1);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值