echo ―How do you do!‖ fi
echo ―ABC‖ exit 0 例2
echo ―Are you girl?please answer Y or N‖ read sex
if test $sex == ―Y‖ then echo ―Hello girl!‖ elif test $sex== ―N‖ then echo ―Hello boy!‖ else
echo ―sorry,$sex not recognized,please entey Y or N‖ exit 1 fi exit 0 例3
for day in Mon Tue Wed Thu Fri Sat Sun do echo $day
done
其执行过程是,变量day依次取值表中各字符串,即第一次将―Mon‖赋给day,然后进入循环体,执行其中的命令,显示出Mon。第二次将―Tue‖赋给day,然后执行循环体中命令,显示出Tue。依次处理,当day把值表中各字符串都取过一次之后,下面day的值就变为空串,从而结束for循环。因此,值表中字符串的个数就决定了for循环执行的次数。在格式上,值表中各字符串之间以空格隔开。
例4
while [ $1 ] do
if [ -f $1 ]
then echo \cat $1
else echo \fi shift done
这段程序对各个给定的位置参数,首先判断其是否是普通文件,若是,则显示其内容;否则,显示它不是文件名的信息。每次循环处理一个位置参数$1,利用shift命令可把后续位置参数左移。
测试条件部分除使用test命令或等价的方括号外,还可以是一组命令。根据其最后一个命令的退出值决定是否进入循环体执行。 例5 编写一个简单的删除程序
#name: del
16
#author: liangnian
#this program to compress a file to the dustbin if test $# -eq 0 then
echo ―Please specify a file!‖ else
gzip $1 //先对文件进行压缩
mv $1.gz $HOME/dustbin //移动到回收站 echo ―File $1 is deleted !‖
fi
10、Shell脚本的建立和执行 (1)Shell脚本的建立
Shell程序可以存放在文件中,这种被Shell解释执行的命令文件称为Shell脚本 (Shell Script)。Shell脚本可以包含任意从键盘键入的Linux命令。
建立Shell脚本的步骤同建立普通文本文件的方式相同,利用任何编辑器(如vi)进行程序录入和编辑加工。例如,要建立一个名为ex1的Shell脚本,可在提示符后输入命令:
$ vi ex1
进入vi的插入方式后,就可录入程序行。完成编辑之后,将编辑缓冲区内容写入文件中,返回到Shell命令状态。 (2)执行Shell脚本
格式:$ bash 脚本名 [参数] 例如:
$ bash ex1 /usr/meng /usr/zhang
Shell从文件ex1中读取命令行,并执行它们。当Shell到达文件末尾时就终止执行,并把控制返回到Shell命令状态。若有参数,则将参数值传递给程序中的命令,使一个Shell脚本可以处理多种情况,就如同函数调用时可根据具体问题给定相应的实参。
第3章 Linux系统调用函数简介
1、fork( ):创建一个新进程 格式:int fork()
其中返回int值的意义如下: 0:创建子进程,从子进程返回
>0:从父进程返回,返回值为子进程的进程标识符 -1:创建失败
2、vfork( ):创建一个新进程
17
格式:int vfork()
其中返回int值的意义如下: 0:创建子进程,从子进程返回
>0:从父进程返回,返回值为子进程的进程标识符 -1:创建失败
vfork()和fork()不同之处在于:在fork调用中,子进程复制父进程的数据区作为自己的数据区,能够继承已有的资源,从而对数据的操作不再影响父进程。vfork()函数在创建子进程后,先于父进程运行,父进程被阻塞,在子进程调用exec或exit之前,子进程与父进程共享数据段,此时可对父进程的数据进行操作。
3、execv():运行可执行文件
格式:int execv(const char *file,char **argv,char **envp) 其中返回int值的意义如下: 0:正确返回 -1:错误返回
当一个进程调用execv函数执行另一个程序后,这个进程被新程序取代,包括代码段、数据段、堆栈段等等,并继承原进程的进程标识符。从自己的main()函数开始执行。新程序使用原进程的进程标识符和进程控制表里的一部分信息。
该函数要用到unistd.h头文件,即在程序中要有#include
Wait函数常用来控制父进程与子进程的同步。在父进程中调用wait函数,则父进程被阻塞,进入等待队列,等待子进程结束。当子进程结束时,会产生一个终止状态字,系统会向父进程发出SIGCHLD信号。当接收到信号后,父进程提取子进程的终止状态字,从wait返回继续执行原程序。该函数适用的头文件如下:
#include
函数格式:pid_t wait(int *statloc) 子进程ID:正确返回 0:其他 -1:错误返回
可以使用系统提供的宏来获得子进程终止时的信息,这些宏定义在sys/wait.h头文件中,具体含义如下:
WIFEXITED(status):子进程正常终止,返回真。 WEXITSTATUS(status):如果WIFEXITED返回真,则该宏返回子进程的exit码。
WIFSIGNALED(status):子进程非正常终止,返回真。 WTERMSIG(status):如果WIFSIGNALED返回真,则该宏返回引起子进程终止的信号值。
WIFSTOPPED(status):子进程已结束,返回真。 WSTOPSIG(status):如果WIFSTOPPED返回真,则该宏返回引起子进程结束的信号值。
5、waitpid()
18
如果父进程创建了多个子进程同时在运行,则父进程中wait函数会捕获它任一个子进程的结束信号,而无法让它确定地去捕获某一个进程的结束信号。Waitpid函数则解决了这个问题。该函数适用的头文件如下:
#include
函数格式:pid_t waitpid(pid_t pid,int *statloc,int options) 子进程ID:正确返回 0:其他 -1:错误返回
参数pid的值决定要求父进程等待的不同特征的子进程,含义如下: 0:与父进程组ID相同的子进程。 >0:进程ID为pid的子进程。
-1:任意子进程。此时与wait函数功能相同。 <-1:进程组ID为pid绝对值的子进程。
Statloc所指的地址用于存放子进程的终止状态字。 Options控制waitpid的执行,常用的参数如WNOHANG:若waitpid函数没得到指定子进程的结束信号,则立即返回零,不会阻塞。
6、exit():结束进程
进程结束最常用的方法是调用exit函数,在main函数中调用的return,最终也是调用exit,这些都属于进程的正常终止。该函数适用的头文件如下:
#include
函数格式:void exit(int status)
Status为进程结束状态。在子进程调用exit后,子进程的结束状态会返回给系统内核,由内核根据状态字生成终止状态,供父进程在wait或waitpid函数中读取。如果子进程结束后,父进程还没有读取子进程的终止状态,则系统就将子进程的状态置为“ZOMBIE”,并保留子进程的进程控制块,里面记录着进程标识符、终止状态字、CPU时间等信息,等父进程读取信息后,系统才彻底释放子进程的进程控制块。
7、msgget():获得一个消息的描述符,该描述符指定一个消息队列以便用于其他系统调用。
该函数适用的头文件如下: #include
函数格式:int msgget(key,flag) key_t key; int flag ;
消息队列的标识符:正确返回 -1: 错误返回
Key是键值,这个键值要与已有的键值进行比较,已有的键值指在内核中已存在的其他消息队列键值。当key的值为IPC_PRIVATE时,创建一个新的消息队列;当key的值不为IPC_PRIVATE时,对消息队列的打开或存取操作依赖于flag参数的取值。
8、msgsnd():发送一条消息给一个消息队列
19
该函数适用的头文件如下: #include
函数格式:int msgsnd(id,smgp,size,flag) int id,size,flag; struct msgbuf* msgp; 消息队列的标识符:正确返回 -1:错误返回
其中:id是返回消息队列的标识符;msgp是指向用户存储区的一个构造体指针,size指示由msgp指向的数据结构中字符数组的长度,即消息队列的长度;flag规定当核心用尽内部缓冲空间时应执行的动作;若在标志flag中未设置IPC_NOWAIT位,则当该消息队列中的字节数超过一最大值时,或系统范围的消息数超过某一最大值时,则调用进程将被阻塞,进入等待队列;若设置IPC_NOWAIT,msgsnd立即返回。
9、msgrcv():从消息队列中接受消息,,将该消息拷贝到消息缓冲区中,返回拷贝的字节数。
该函数适用的头文件如下: #include
函数格式:int msgsnd(id,smgp,size,type,flag)
int id,size,type,flag;
struct msgbuf* msgp;
接收到消息缓冲区的字节数:正确返回 -1:错误返回
其中,id指定要接收的消息队列;msgp是存放消息的消息缓冲区的地址指针;size是消息缓冲区的大小;type是用户要读的消息类型,取值有三种:
(1)type>0:查找消息队列中与该类型相匹配的第一条消息。 (2)type==0:接收该队列的第一个消息。
(3)type<<0:接收小于或等于type绝对值的最低类型的第一个消息。 flag的含义同上一个函数,如果值为IPC_NOWAIT,并且没有可取的消息,则带错返回调用进程。否则,调用进程阻塞进入阻塞队列,直到一条消息到达队列并且满足接收条件。
10、lockf(files,mode,size):用于锁定文件的某些段或者整个文件. 本函数的头文件为 #include unistd.h 函数格式:
int lockf(files,mode,size) int files,mode; long size;
其中:files是文件描述符;mode是锁定和解锁:1表示锁定,0表示解锁.size是锁定或解锁的字节数,为0,表示从文件的当前位置到文件尾.
20