Linux系统编程——进程

一、概述

(1)什么是程序?

程序是静态的概念,在我们进行编译操作后,磁盘中会生成一个可执行的文件,它就叫做程序。

(2)什么是进程?

程序运行起来了,那么系统中就会多了一个进程。

(3)程序和进程的区别

程序是静态的,而进程是动态的。
程序是永久的,而进程是暂时存在的。
进程是程序的一次执行,而进程总是对应至少一个特定的程序。

(4)进程的生命周期

1、就绪状态:进程已经做好了运行的准备,只需要获得内存空间,就可以立即执行

2、阻塞状态:进程的某些请求无法获取,暂时无法继续执行的状态。(注意:进程只能自己阻塞自己,因为只有进程自己知道还需要哪些特定的事件,才能开始运行)

3、执行状态:进程以进入内存,在CPU的处理下,进行执行

4、对进程进行唤醒

5、进程结束

二、怎么查看系统中有哪些进程

(1)使用ps指令查看,在实际工作中,配合grep来查找程序中是否存在某一个进程

ps aux                     #查看进程使用情况

ps aux | less              #查看进程使用情况,考虑到显示过多,使用分管符和less命令查看

ps aux --sort CPU          #查看进程使用情况,并按照CPU的使用率升序排列

ps aux --sort -CPU         #查看进程使用情况,并按照CPU的使用率降序排列

ps aux --sort rss          #查看进程使用情况,并按照内存的使用升序排列

ps aux --sort -rss         #查看进程使用情况,并按照内存的使用降序排列

ps -ef | grep XXX          #查看指定的进程是否开启

ps axo user,pid,ppid……     #查看进程,并且只查看后面列举出的信息

上述显示中:

USER:代表该进程的用户

PID:表示进程ID

%CPU:是CPU的占用率

%MEM:是内存占用率

VSZ:是占用虚拟内存

RSS:是占用实际内存

TTY:是指进程运行的终端

STAT:是指进程运行的状态

START:是进程启动的时间

TIME:是进程占用CPU的时间

COMMAND:是进程对应的程序

STAT一列中,进程状态含义:

R:运行
S:可中断睡眠
D:不可终端睡眠
T:停止的进程
Z:僵尸进程
X:死掉的进程
Ss:表示该进程是一个父进程,本身有子进程
S<:表示优先级较高的进程
SN:表示优先级较低的进程
R+:表示前台进程
Sl:表示以线程方式运行的进程

(2) 使用top指令查看,类似windows任务管理器

top命令可以动态查看进程,top命令常用参数如下:
-d :表示刷新的时间间隔,单位为s
-p :表示查看指定PID的进程
-u :表示查看指定用户的进程
-n :表示top刷新指定次数后退出

//top命令使用示例
top -d 1
top -p 100
top -n 3 >123.txt
top -u nginx

上述四条命令都表示用top查看系统进程:

第一条命令表示刷新时间为1秒,

第二条命令表示只查看PID100的进程,

第三条表示将top刷新3次的结果写入到123.txt文档中,

第四条表示只显示用户为Nginx的进程。

 三、什么是进程标识符

进程都有一个非负整数表示唯一ID,就做pid,相当于我们的身份证

Pid = 0:叫做交换进程(swapper)

作用:进行进程调度

Pid = 1:init进程

作用:进行系统初始化

//调用getpid函数获取自身进程标识符(getppid获取父进程的进程标识符)
#include <stdio.h>

int main()
{
    pid_t pid;
    
    pid = getpid();
    
    printf("my pid is:%d\n",pid);

    return 0;
}

 四、什么叫父进程,什么叫子进程

进程A创建了进程B,那么A叫做父进程,B为子进程,父子进程是相对的概念,可以理解成儿子和父亲之间的父子关系。

五、C程序的存储空间是如何分配的


六、进程创建实战

(1)如何使用fork函数创建一个进程

1.1 fork函数原型

pid_t fork(void)

注意:如果fork函数调用成功,会返回两次,

返回值为0(代表当前进程是子进程),

返回值为非负数(代表当前进程是父进程),

调用失败返回-1

 1.2 fork创建子进程的目的

1.2.1 父进程希望复制自己,使父、子进程同时执行不同的代码段。这在网络服务进程中是常见的——父进程等待客户端的服务请求。当这种请求到达时,父进程调用fork,使子进程处理此请求。父进程则继续等待下一个服务请求到达。

1.2.2 进程要执行一个不同的程序。这对shell是常见的情况。在这种情况下,子进程从fork返回后立即调用exec

(2) fork编程实战

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main()
{
    pid_t pid;
    pid_t pid2;

    pid = getpid();
    printf("before fork:pid = %d\n",pid);

    fork(); //fork之后

    pid2 = getpid();
    printf("after fork:pid = %d\n",pid2);

    if(pid == pid2){
        printf("this is father print\n");
    }else{
        printf("this is child print,child pid = %d\n",getpid());
    }

    return 0;
}

七、vfork函数与fork函数有什么区别

1、vfork 直接使用父进程存储空间,不拷贝

2、vfork 保证子进程先运行,当子进程调用exit退出后,父进程才执行

//vfork创建进程

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
        pid_t pid;

        int cnt = 0;

        pid = vfork();

        if(pid > 0){
            while(1){
                printf("this is father print,pid = %d\n",getpid());
                sleep(1);
                printf("cnt = %d\n",cnt);
            }
        }
        else if(pid == 0){
            while(1){
                printf("this is child print,pid = %d\n",getpid());
                sleep(1);
                cnt++;
                if(cnt == 3){
                    exit(0);
                }
            }
        }

        return 0;
}

八、进程的退出

1、正常退出

        1.1、main函数调用 return

        1.2、进程调用 exit(),属于标准的C库

        1.3、进程调用 _exit() 或者 _Exit() ,属于系统调用

        补充:

        1.4、进程最后一个线程返回

        1.5、最后一个线程调用 pthread_exit

2、异常退出

        2.1、调用abort

        2.2、当进程收到某些信号时,如 ctrl+C

        2.3、最后一个线程对取消 (cancellation)请求做出响应

3、父进程等待子进程退出

        3.1、等待子进程退出后收集子进程的退出状态,子进程退出状态如果不被收集,将会变成僵死的进程。

        3.2、wait 与 waitpid 的区别:wait 使调用者阻塞,waitpid 有一个选项,可以使调用者不阻塞

//父进程等待子进程退出

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
        pid_t pid;

        int cnt = 0;
        int status = 10; //用于返回wait的值

        pid = fork();

        if(pid > 0){
            wait(status);
            printf("wait:%d\n",WEXITSTATUS(status));
            while(1){
                printf("this is father print,pid = %d\n",getpid());
                sleep(1);
                printf("cnt = %d\n",cnt);
            }
        }
        else if(pid == 0){
            while(1){
                printf("this is child print,pid = %d\n",getpid());
                sleep(1);
                cnt++;
                if(cnt == 5){
                    exit(3);
                }
            }
        }

        return 0;
}

注意:

(1)如果其所有子进程都还在运行,则阻塞。

(2)如果一个子进程已终止,正在等待父进程获取其终止状态,则取得该子进程的终止状态立即返回

(3)如果它没有任何子进程,则立即出错返回

4、孤儿进程

(1)父进程如果不等待子进程退出,在子进程之前就结束了自己的“生命”,此时子进程叫做孤儿进程

(2)linux为了避免系统存在过多的孤儿进程,init进程收留孤儿进程,变成孤儿进程的父进程

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值