shell编程学习五

来源:互联网 发布:mac上建模软件 编辑:程序博客网 时间:2024/05/02 03:05

1. 什么是程序,什么又是进程

程序是指令的集合,而进程则是程序执行的基本单元,为了让程序完成它的工作,我们必须让程序运行起来成为进程,进而

利用处理器资源,内存资源,进行各种I/O操作,完成某项指定的工作。

程序是静态的,而进程则是动态的

它们的区别还在于,进程除了包含程序文件中的指令数据外,还需要在内核中有一个数据结构用以存放特定的进程相关属性

,以便内核更好的管理和调度进程,从而完成多进程协作的任务。

如果进行过多进程程序开发,会发现,一个程序可能创建多个进程,通过进程的交互完成任务。在Linux下,多进程的创建通

常是通过多个fork系统调用来实现的,从这个意义上说程序则“包含”了进程。

另外一个需要明确的是,程序可以由多种不同程序语言描述,包括C语言程序,汇编语言程序,和最后编译产生的机器指令等


2, Linux下如何通过shell进行进程的相关操作 -- 进程的创建

通常在命令行键入摸个程序的文件名后,一个进程就被创建了

$ sleep 100 &       #让sleep程序在后台运行

[1] 5311

$ pidof sleep        #用pidof可以查看指定程序名的进程ID

5311

$ cat /proc/5311/maps    #查看进程的内存映像

        当一个程序被执行以后,程序被加载到内存中,称为一个进程,可以查看内存映像(虚拟内存),包括程序指令、数据、以及

一些用于存放程序命令行参数、环境变量的栈空间,用于动态内存申请的堆空间都被分配好


         实际上,创建一个进程,也就是说让程序运行,例如,通过一些配置让系统启动时自动启发我们的程序(具体参考"man init")

或者通过配置crond(或者at)让它定时启动我们的程序。除此之外,还有一个方式,那就是通过编写shell脚本,把程序写入一个

脚本文件,当执行脚本文件时,文件中的程序将被执行而成为可执行程序。

         在命令下执行程序时,可以通过ulimit内置命令来设置程序可以利用的资源, 参见"help ulimit"


3,查看进程的属性和状态

可以通过ps命令查看进程的相关属性和状态, 这些信息包括进程所属用户,进程对应的程序,进程对cpu和内存的使用情况等信息,

熟悉如何查看它们有助于我们进行相关的统计分析和进一步操作

$ ps -ef   #查看系统所有当前进程的属性

$ ps -C init       #查看命令中包含某个指定字符的程序对应的进程,进程ID是1,TTY为?,表示和终端没有关联

$ ps -U  falcon    #选择摸个特定用户启动的进程

$ ps -e -o "%C %c"    #可以按照指定格式输出指定内容,这里会输出命令和cpu使用率

$ ps -e -o "%C %c" | sort -u -k1 -r | head -5      #这样则会打印cpu使用率最高的前四个程序

$ ps -e -o "%z %c"  | sort -n -k1 -r | head -5       #使用虚拟内存最大的5个进程


由于系统所有进程之间存在关联,可以用pstree查看这种关系

$ pstree    #打印系统进程调用树,可以非常清楚看到当前系统中所用活动进程之间的调用关系

动态查看进程信息

$ top 


4, 调整进程的优先级

在保证每个进程都能够顺利执行外,为了让某些任务优先完成,那么系统在进行进程调度时就会采用一定的调度办法,例如常见

的有按照优先级的时间片轮转的调度算法,这种情况下,可以通过renice调整正在运行的程序优先级

$ ps -e -o "%p %c %n " | grep netns   #打印的信息分别是进程ID, 进程对应的程序名,优先级

$ renice 1 -p  15   #调整优先级,通常需要权限才能执行



5,结束进程 


既然可以通过命令行执行程序,创建进程,那么也有办法结束它。可以通过kill命令,给用户自己启动的进程发送一定信号让进程终止


kill默认会发送终止信号(SIGTERM)给程序,让程序退出,但是kill还可以发送其他的信号,这些信号的定义我们可以通过

man 7 signal查看到,也可以通过kill -l 列出来

$ man 7 signal

$kill -l 

例如可以通过发送SIGSTOP信号给某个程序,让它暂停,然后发送SIGCONT信号让它继续运行


6,进程通信


     为了便于设计和实现,通常一个大型的任务都被划分为较小的模块,不同的模块之间启动后成为进程,他们之间如何通信

以便交互数据,协同工作?方法很多,如管道、信号、报文、消息队列、共享内存、信号量、套接口等

在shell编程里,通常直接用到的就是管道和信号灯,


管道

》无名管道(pipe)

在Linux下,可以通过“|”连接两个程序,这样就可以用它来连接一个程序的输入和前一个程序的输出,形象的叫它管道。在C语言中

创建无名管道非常简单方面,用pipe函数,传入一个具有两个元素的int型的数组就可以,这个数组可以从第一个文件描述符中读出

来。

如果用多了命令行,这个管子“|”应该会经常用,

$ ps -ef | grep init

实际上,当输入一组命令时,当前解释程序会进行适当的解析,把前面一个进程的输出关联到管道的输出文件描述符,吧后面一个

进程的输入关联到管道的输入文件描述符,这个关联过程通过输入输出重定向函数dup(或者fcntl)来实现


》有名管道


有名管道实际上是一个文件(无名管道也像一个文件,虽然关系到两个文件描述符,不过只能一边读另外一边写),不过这个文件

比较特别,操作时要满足先进先出,如果试图读一个没有内容的有名管道,那么就会被阻塞,同样的,如果试图往一个有名管道里

写东西,而当前没有程序试图读它,也会被阻塞。

$ mkfifo  fifo_test   #通过mkfifo命令可以创建一个有名管道

$ echo "fewfefe"  > fifo_test     #试图往fifo_test文件中写入内容,但是被阻塞,要 另开一个终端继续下面的操作

$ cat fifo_test      #另开一个终端,读出fifo_test的内容


    在这里echo和cat是两个不同的程序,在这种情况下,通过echo和cat启动的两个进程之间便命有父子关系。不过它们依然

可以通过有名管道通信,这样一种通信方式非常适合某些情况:如有这样一个架构,这个架构由两个应用程序构成,其中一个

通过一个循环不断读取fifi_test中的内容,以便判断,它下一步做什么。如果这个管道没有内容,那么它就会被阻塞在那里,

而不会死循环而耗费资源,另外一个则作为一个控制程序不断的往fifo_test中写入一些控制信息,以便告诉之前的那个程序该做什么

。下面写一个简单的例子。设计一个控制码,然后控制程序不断网fifo_test里写入,然后应用程序根据这些控制码完成不同的动作

,当然,也可以网fifo_test传入除了控制码外的不同的数据

$ cat app.sh     #应用程序的代码

#!/bin/bash

FIFO=fifo_test

while :;

do

           CI=`cat $FIFO`      #CI --> Control Info

           case $CI  in

                    0)   echo "The Control number is ZERO, do something ....."

                                 ;;

                      1)   echo "The control nmber is ONE , do something...."

                                 ;;

                         *) echo "The control Number not recognized, do something ....."

                                 ;;

                  esac

done


$  cat control.sh             #控制程序的代码

#!/bin/bash

FIFO=fifo_test

CI=$1

[ -z "CI" ] && echo "The control info should not be empty" && exit

echo $CI > $FIFO


$chmod +x app.sh control.sh          #修改这两个程序的可执行权限,以便用户可以执行它们

$ ./app.sh                                       #在一个终端启动这个应用程序,在通过./control.sh发送控制码以后查看输出


$ ./control.sh    1                 #在另外一个终端,放送控制信息,控制应用程序的工作



这样一个应用架构非常适合本地多个程序任务的设计,如果结果web cgi,那么也将适合远程控制的要求。


》信号(Signal)

信号是软件中断,在Linux下用户可以通过kill命令给某个程序发送一个特定的信号,也可以通过键盘发送一个信号,例如

Ctrl+C可以触发CGIINT信号,而Ctrl+\可能触发SGIQUIT信号等,除此之外,内核在某些情况下,也会给进程发送信号。

例如访问内存越界时产生SGIEGV信号。


7,作业和作业控制

     当为完成一些复杂的任务而将多个命令通过|,<,>,;,(,)等组合在一起的时候,通常这样个命令序列会启动多个进程,

它们之间通过管道等进行通信,而有些时候,我们执行一个任务的同时,还有其他的任务需要处理,那么就经常会子啊命令序列

后面加上一个&,或者执行命令以后,按下Ctrl+Z 让前一个命令暂停,一边做其他任务。等做完其他一些任务以后,在通过fg命令



0 0
原创粉丝点击