linux实现彩色进度条,rpm和yum安装的区别和进程的task_struck结构

来源:互联网 发布:淘宝网美国大樱桃 编辑:程序博客网 时间:2024/05/29 14:38

一、在Linux下实现进度条程序. 通过makefile进行编译. 建议自主完成一个彩色的进度条.

1.什么是进度条?

进度条:进度条是在计算机处理任务时,以图片形式显示处理任务的进度的一种显示。

2.要设计一个什么样的进度条呢?

那么我们经常见的进度条包括有长方形的条状强调内容从短短的一点一点开始慢慢变长的一个长方体块我们用#代替,还包括一个完成的百分数,当完成时会到达100%。

3.进度条如何缓慢显示?

想到以前想在屏幕上缓慢显示一个数或者一个字符时,我们常常会用sleep/usleep(微妙为单位)函数。

4.那么说了那么多,我们有了一些对问题的认识,就开始在linux环境下用vim写一个彩色的进度条

1).新建一个progressbar.c文件
这里写图片描述
2)progressbar.c文件代码
这里写图片描述
3).写Makefile文件运行进度条。
这里写图片描述
4).运行并显示结果.
这里写图片描述

5.Makefile文件的用法和作用.

写完processbar.c文件后我们通常会用gcc processbar.c编译这个程序然后会生成一个a.out的文件只要我们输入./a.out程序就会运行,既然这个方法就可以完成这个事情,那么我们为什么还特别的写一个makefile文件去运行makefile文件呢?
makefile的作用是:命令行编译连接命令nmake使用的文件。它以文本的方式规定了make要编译那些文件,生成那些文件,要连接那些文件,生成的.exe文件的名称等。

当前我们遇到的项目源文件只有一个,此时我们可以采用4条或者2条命令完成编译链接等工作,但如果源文件有若干个.c和.h文件组成呢,makefile文件就可以快速批量的进行编译链接。因此,makefile文件就显得极其重要了。

二、调研Linux下软件安装的几种方式(源码安装, rpm安装, yum安装). 重点要理解rpm安装和yum安装的区别.

1、rpm包安装方式步骤:

1)、找到相应的软件包,比如soft.version.rpm,下载到本机某个目录;2)、打开一个终端,su -成root用户; 3)、cd soft.version.rpm所在的目录; 4)、输入rpm -ivh soft.version.rpm

详细介绍:
1.1. 安装:
  我只需简单的一句话,就可以说完。执行:
  rpm –ivh rpm的软件包名
  更高级的,请见下表:
  rpm参数 参数说明
  -i 安装软件
  -t 测试安装,不是真的安装
  -p 显示安装进度
  -f 忽略任何错误
  -U 升级安装
  -v 检测套件是否正确安装
  这些参数可以同时采用。更多的内容可以参考RPM的命令帮助。
1.2. 卸载:
  我同样只需简单的一句话,就可以说完。执行:
  rpm –e 软件名
  不过要注意的是,后面使用的是软件名,而不是软件包名。例如,要安装software-1.2.3-1.i386.rpm这个包时,应执行:
  rpm –ivh software-1.2.3-1.i386.rpm
  而当卸载时,则应执行:
  rpm –e software。

2.yum方式安装:(安装rpm包)

rpm 是linux的一种软件包名称,以.rmp结尾,安装的时候语法为:rpm -ivh。
rpm包的安装有个很大的缺点就是文件的关联性太大,有时装一个软件要安装很多其他的软件包,很麻烦。
所以为此RedHat小红帽开发了yum安装方法,他可以彻底解决这个关联性的问题,很方便,只要配置两个文件即可安装,安装方法是:yum -y install 。
yum并不是一中包,而是安装包的软件
简单的说: rpm 只能安装已经下载到本地机器上的rpm 包. yum能在线下载并安装rpm包,能更新系统,且还能自动处理包与包之间的依赖问题,这个是rpm 工具所不具备的。

3.rpm和yum的区别:

rpm

* 用来安装已经下载在本地机器上的rpm包,类似Windows里面的“添加/删除程序”* 可以发现并提示某个依赖包尚未安装,但需要手动先安装依赖包

yum

* 能够自动下载并安装rpm包* 能够处理包的依赖关系* 能够更新系统* 使用存储库(repository),即包的集合

三、调研task_struct结构体, 理解结构体中的各个字段的含义

在广义上,所有进程信息都被放在一个叫做进程控制块的数据结构中,那么什么是进程控制块呢?

1.进程控制块(PCB)

每个进程在内核中都有一个进程控制块(PCB)来维护进程的相关信息,Linux内核的进程控制块是task_struct结构体。它会被装载到RAM里并且包含着进程的信息,每个进程都会把它的进程的相关信息放在task_struct数据结构中,task_struct主要包含了下面这些内容:

标识符:描述本进程的唯一标识符,用来区别其他进程。
状态:任务状态、退出代码、退出信号等。
优先级:相对于其他进程的优先级。
程序计数器(PC):程序中即将被执行的下一条指令的地址。
内存指针:包括程序代码和进程相关数据的指针,还有和其它进程共享的内存块的指针。
上下文数据:进程执行时处理器的寄存器中的数据。
I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
记账信息:可能包括处理器时间总和,使用的时钟数综合、时间限制、记账号等。

下面是对它们的详细说明:
·进程状态
进程执行时,它会根据具体情况改变状态 。进程状态是调度和对换的依据。Linux中的进程主要有如下状态,如表4.1所示。
这里写图片描述

·可运行状态
处于这种状态的进程,要么正在运行、要么正准备运行。正在运行的进程就是当前进程(由current所指向的进程),而准备运行的进程只要得到CPU就可以立即投入运行,CPU是这些进程唯一等待的系统资源。系统中有一个运行队列(run_queue),用来容纳所有处于可运行状态的进程,调度程序执行时,从中选择一个进程投入运行。在后面我们讨论进程调度的时候,可以看到运行队列的作用。当前运行进程一直处于该队列中,也就是说,current总是指向运行队列中的某个元素,只是具体指向谁由调度程序决定。

·等待状态
处于该状态的进程正在等待某个事件(event)或某个资源,它肯定位于系统中的某个等待队列(wait_queue)中。Linux中处于等待状态的进程分为两种:可中断的等待状态和不可中断的等待状态。处于可中断等待态的进程可以被信号唤醒,如果收到信号,该进程就从等待状态进入可运行状态,并且加入到运行队列中,等待被调度;而处于不可中断等待态的进程是因为硬件环境不能满足而等待,例如等待特定的系统资源,它任何情况下都不能被打断,只能用特定的方式来唤醒它,例如唤醒函数wake_up()等。

·暂停状态
此时的进程暂时停止运行来接受某种特殊处理。通常当进程接收到SIGSTOP、SIGTSTP、SIGTTIN或 SIGTTOU信号后就处于这种状态。例如,正接受调试的进程就处于这种状态。
·僵死状态
进程虽然已经终止,但由于某种原因,父进程还没有执行wait()系统调用,终止进程的信息也还没有回收。顾名思义,处于该状态的进程就是死进程,这种进程实际上是系统中的垃圾,必须进行相应处理以释放其占用的资源。

2. 进程调度信息

调度程序利用这部分信息决定系统中哪个进程最应该运行,并结合进程的状态信息保证系统运转的公平和高效。这一部分信息通常包括进程的类别(普通进程还是实时进程)、进程的优先级等等。如表4.2所示:
这里写图片描述

3 .标识符(Identifiers)

每个进程有进程标识符、用户标识符、组标识符,如表4.4所示。
这里写图片描述
不管对内核还是普通用户来说,怎么用一种简单的方式识别不同的进程呢?这就引入了进程标识符(PID:process identifier),每个进程都有一个唯一的标识符,内核通过这个标识符来识别不同的进程,同时,进程标识符PID也是内核提供给用户程序的接口,用户程序通过PID对进程发号施令。PID是32位的无符号整数,它被顺序编号:新创建进程的PID通常是前一个进程的PID加1。然而,为了与16位硬件平台的传统Linux系统保持兼容,在Linux上允许的最大PID号是32767,当内核在系统中创建第32768个进程时,就必须重新开始使用已闲置的PID号。

4. 进程通信有关信息(IPC:Inter_Process Communication)

为了使进程能在同一项任务上协调工作,进程之间必须能进行通信即交流数据。
Linux支持多种不同形式的通信机制。它支持典型的Unix 通信机制(IPC Mechanisms):信号(Signals)、管道(Pipes),也支持System V 通信机制:共享内存(Shared Memory)、信号量和消息队列(Message Queues),如表4.5。
这里写图片描述

程序创建的进程具有父/子关系。因为一个进程能创建几个子进程,而子进程之间有兄弟关系,在task_struct结构中有几个域来表示这种关系。
在Linux系统中,除了初始化进程init,其他进程都有一个父进程(parent process)或称为双亲进程。可以通过fork()或clone()系统调用来创建子进程,除了进程标识符(PID)等必要的信息外,子进程的task_struct结构中的绝大部分的信息都是从父进程中拷贝,或说“克隆”过来的。系统有必要记录这种“亲属”关系,使进程之间的协作更加方便,例如父进程给子进程发送杀死(kill)信号、父子进程通信等,就可以用这种关系很方便地实现。
每个进程的task_struct结构有许多指针,通过这些指针,系统中所有进程的task_struct结构就构成了一棵进程树,这棵进程树的根就是初始化进程init的task_struct结构(init进程是Linux内核建立起来后人为创建的一个进程,是所有进程的祖先进程)。表4.6是进程所有的链接信息。
这里写图片描述

6. 和处理器相关的环境(上下文)信息(Processor Specific Context)

这里要特别注意标题:和“处理器”相关的环境信息。进程作为一个执行环境的综合,当系统调度某个进程执行,即为该进程建立完整的环境时,处理器(processor)的寄存器、堆栈等是必不可少的。因为不同的处理器对内部寄存器和堆栈的定义不尽相同,所以叫做“和处理器相关的环境”,也叫做“处理机状态”。当进程暂时停止运行时,处理机状态必须保存在进程的task_struct结构中,当进程被调度重新运行时再从中恢复这些环境,也就是恢复这些寄存器和堆栈的值。处理机信息如表4.13所示。
这里写图片描述

综上所述,我们对进程的task_struct结构进行了归类讨论,task_struct结构是进程实体的核心,Linux内核通过该结构来控制进程:首先通过其中的调度信息决定该进程是否运行;当该进程运行时,根据其中保存的处理机状态信息来恢复进程运行现场,然后根据虚拟内存信息,找到程序的正文和数据;通过其中的通信信息和其他进程实现同步、通信等合作。几乎所有的操作都要依赖该结构,所以,task_struct结构是一个进程存在的唯一标志。

原创粉丝点击