嵌入式LINUX---------进程

  • top:动态查看 系统中进程 ---类似windows下任务管理器
  • pstree:查看进程树,加一个   -sp:可显示pid ;sp +pid号可以查看该pid进程的一条进程树
  • kiil:作用是发信号;kill -l:可以查看可以发送的信号;kill -信号序号  +pid
  • killall -号 +要被操作的名字:杀死同名的
  • ps  -elf | grep a.out:查看pid、ppid号
  • ps aux  | grep a.out:查看pid、状态信息
  •  int atexit(void (*function)void):注册一个退出清理函数,,成功返0;function是一个函数指针,类型void func(void)类型的

一、进程

1.进程的含义


        进程是一个程序执行的过程,会去分配内存资源,cpu的调度(程序的一次执行过程)

2.pcb  是一个结构体,process control block
vim -t
task_struct (pcb块的名字,这个是linu的名儿)
(1)PID,进程标识符
(2)当前工作路径   chdir
(3)umask  0002
(4)进程打开的文件列表  文件IO中有提到
(5)信号相关设置 处理异步io,
(6)用户id,组id(是一种权限)
(7)进程资源的上限
(8)ulimit -a,显示资源上限。

2.进程和程序的区别


(1)程序:静态
        存储在硬盘中代码,数据的集合


(2)进程:动态
        程序执行的过程,包括进程的创建、调度、消亡
        1)程序是永存,进程是暂时的
        2)进程有程序状态的变化,程序没有
        3)进程可以并发,程序无并发
        4)进程与进程会存在竞争计算机的资源(几个进程同时操作一个文件)
        5)一个程序可以运行多次,变成多个进程;一个进程可以运行一个或多个程序

code:代码 只读

data/bss:数据段:放全局变量、静态变量,可读可写(bss:未初始化的全局变量和静态变量)

heap:堆区:动态内存空间,由程序员申请释放,用大空间来堆区申请

map/share映射区、共享区:栈区:把外面的某一段空间映射进来,好处是代码只需要一份,把a.out的体积变小

stack:栈区:8M

ELF:a.out中有ELF(head)、code、data

MMU:内存管理单元,把物理地址变成虚拟地址,为了透明(给a.out制造访问物理地址的假象)、隔离、权限(安全)。

3.进程的诞生

(1)早期

(2)多核,实现真正意义上的并行运行

3.内存的分布
0-3G,是进程的空间,3G-4G是内核的空间,虚拟地址
虚拟地址 *  物理内存和虚拟内存的地址 映射表 1page=4k    mmu

4.进程分类:
(1)交互式进程
(2)批处理进程   shell脚本 
(3) 守护进程 :守护计算机安全,这类不需要输入,自己运行例如:杀毒类软件、输入法......

5.进程的作用: 并发;
while (1) 

{

        while (1) 

        { 

                上下左右;
                发视频(两状态时延越少越好,所有两个状态同时进行);
        }

}
6.进程的状态:
        3个状态,就绪→执行态→阻塞(等待,睡眠,scanf)基本操作系统linux中的状态,运行态,睡眠态,僵尸,暂停态。无法从阻塞态直接到执行态,必须经过一个就绪态,由操作系统来决定的

linux的状态运行图

7.进程的调度,进程上下文切换
        内核主要功能之一就是完成进程调度, 硬件,bios,io,文件系统,驱动
调度算法, other,idle,rr,fifo
宏观并行:从一个时间段上来说
微观串行:从一个时间点上来说,在某一个进程上面

调度发展:先来先服务->短任务优先-->优先级->多级任务队列(前面三个结合起来)->时间片流转

实时操作系统:rt_thread ucos规定时间内,任务必须完成,对时间要求苛刻,超时影响大;

分时操作系统:linux windows .....尽量在规定时间完成,超时影响不大,对时间要求不太苛刻;

8..查询进程相关命令
(1).ps aux



查看进程相关信息

        1)就绪态、运行态 R
        2)睡眠态、等待态
              可唤醒等待态 S:可中断的睡眠态,浅度睡眠
          *不可唤醒等待态 D:深度睡眠,
        3)停止态 T:暂停
        4)僵尸态 Z“zombie”,没被父进程回收
        5)死.结束态X

        6)交互        I

  • <高优先级
  • N低优先级
  • L:实时io
  • s:绘画组组长
  • l:多线程程序

(2)top:根据CPU占用率查看进程相关信息

(3)kill和killall发送一个信号
kill -2 PID  15(发2号信号,接收者时PID);


发送信号+PID对应的进程,默认接收者关闭

killall -9 进程名
发送信号 进程名对应的所有进程

4.fork();pid_t fork(); 叉子
(1)特征:

        1)一次调用,会返回两次。

        2)子进程先运行和是父进程先进程,顺序不确定。
        3) 变量不共享(),父子空间独立,各个段都是独立的,互相之间的数据操作,互不影响。

        4)子进程复制父进程的0到3g空间和父进程内核中的PCB,但id号不同。
(2)功能:

          1)通过该函数可以从当前进程中克隆一个同名新进程。
          2)克隆的进程称为子进程,原有的进程称为 父进程。
          3)子进程是父进程的完全拷贝。
          4)子进程的执行过程是从fork函数之后执行。
          5)子进程与父进程具有相同的代码逻辑。

(3)返回值:int 类型的数字。
        在父进程中:成功 返回值是子进程的pid号 >0,失败 返回-1;
        在子进程中:成功 返回值 0,失败 无
面试题:
一次fork生成几个进程?他们之间的关系是什么样的?
如果两次fork同时前后执行,会生成几个进程?他们之间的
关系如何表示,有多少个子进程,有没有孙进程?

面试题:

5.getpid:pid_t getpid(void);
(1)功能:获得调用该函数进程的pid
(2)参数:缺省
(3)返回值:进程的pid
       
6.getppid:pid_t getppid(void);
(1)功能:获得调用该函数进程的父进程pid号
(2)参数:缺省
(3)返回值:返回父进程id号

7.父子进程的关系:

(1)子进程是父进程的副本。子进程获得父进程数据段,堆,栈,正文段共享。

(2)在fork之后,一般情况那个会先运行,是不确定的。如果非要确定那个要先运行,需要IPC机制。

(3)区别:
1)fork的返回值
2)pid不同

(4)写时复制:在fork之后,子进程先不开0~3g空间,在变量发生改变的时候(不管是父还是子的),才会开空间,,如果只是读的话,那就不另开空间,开的空间小,回收的时候也快;

9.进程的终止:8中情况

(1)主动退出:
        1)main 中return
        2)void exit(int status), c库函数,会执行io库的清理工作,关闭所有 的流,以及所有打开的文件。已经清理函数(atexit)。

  • _
    #include<stdio>
    #include <stdlib.h>
    #include <uni.h>
    int mian(void)
    {
        printf("-------");
        exit(1);//清理io缓存,刷新出------
        _exit(1);//直接退出,不刷新--------
    }
    exit():不管在任意位置,调这个函数的进程立马结束,并且把该释放的资源全部释放,一般用于;
  • exit在c库里,_exit在系统调用库里。

        3)_exit,_Exit 会立刻、立即、马上关闭所有的已经打开的文件,不执行清理函数。(系统调用)。

  • 在exit的时候,会注册 int atexit(void (*function)void):注册一个退出清理函数,,成功返0;function是一个函数指针,类型void func(void)类型的

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void clean1(void)
{
    printf("clean1-----exit----\n");
}
void clean2(void)
{
    printf("clean2-----exit----\n");
}
void clean3(void)
{
    printf("clean3-----exit----\n");
}

int	main(int argc, char **argv)
{
    atexit(clean1);
    atexit(clean2);
    atexit(clean3);
    int i =0;
    for(i = 0;i<5;++i)
    {
        printf("i = %d\n",i);
        sleep(1);
    }
    
    _exit(1);
    exit(1);

    return 0;
}


        4) 主线程退出
        5)主线程调用pthread_exit:退该线程,如果时退主线程,那就会进程结束
(2)异常终止:发生了严重的错误,程序无法再进行
        1)abort()(不许应用层调,系统发现本次程序,会发生非常严重的错误,不用做任何回收工作,则终止,)
        2)signal   kill pid
        3)最后一个线程被pthread_cancle

  • 进程包含线程,进程中至少包含一个线程;

10.fork后,

  • 先杀死父进程 观察子进程,由init(1)接管子进程成为其父进程,即init收养子进程(此时叫孤儿进程),此时,按ctrl+c无法关掉,因为子进程变成后台进程,而ctrl+c只能结束前台进程
  • 先杀死子进程,,子进程结束,但是父进程,没有对子进程收尸(僵尸态:是有危害的,消耗内存),就是没有回收(pcb块还在)。

作业:

1.调度算法

- **先来先服务(FCFS)**:按请求到达顺序处理

- **短作业优先(SJF)**:优先执行预计运行时间短的进程

- **优先级调度**:基于优先级分配资源

- **轮转调度(Round Robin)**:每个进程获得固定时间片

- **多级队列调度**:将进程分组并使用不同调度策略

2.文件的写入测试。 设计一个程序,动态生成1个进程,分别向相同的文件中 写入不同的数据,要表明是两个进程同时写入的数据。 ./a.out ===> 1.txt ==>父进程写入的信息 时间+编号(father pid) //time localtime

#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
int	main(int argc, char **argv)
{
    FILE *fp = fopen("01.txt", "w");
    pid_t pid = fork();
    if(pid<0)
    {
        perror("fork");
        return 1;
    }
    if(pid >0)
    {
        while (1)
            {
                time_t sec;
                sec = time(NULL);
                struct tm *tminfo=localtime(&sec);
                fprintf(fp,"father: pid = %d 时间: %d:%d:%d\n",getpid(),tminfo->tm_hour,tminfo->tm_min,tminfo->tm_sec);
                fflush(fp);
                sleep(1);
            }
        
    }
    else if(0 == pid)
    {
        while (1)
        {
            time_t sec;
            sec = time(NULL);
            struct tm *tminfo=localtime(&sec);
            fprintf(fp,"chile: pid = %d 时间: %d:%d:%d\n",getpid(),tminfo->tm_hour,tminfo->tm_min,tminfo->tm_sec);
            fflush(fp);
            sleep(3);
        }
        
    }
    fclose(fp);


    return 0;
}

3.指定创建n个进程

#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int	main(int argc, char **argv)
{
    int i =0;
    int num = 0;
    scanf("%d",&num);
    printf("father: pid = %d\n",getpid());
    for(i =0;i<num;++i)
    {
        pid_t pid = fork();
        if(pid<0)
        {
            perror("fork");
            return 1;
        }
        if(pid>0)
        {
            continue;

        }
        else if(0== pid)
        {
            printf("child  :pid = %d\n",getpid());
            break;
        }
    }
    

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值