无名管道

Download Report

Transcript 无名管道

Linux环境及Shell程序
操作系统实验1
二、Shell编程与进程通信
常用shell命令

文件及文件属性操作



输入输出操作




cd、 pwd、 ls
mkdir、 cp、 mv、 rm -r
文本过滤


echo 、cat
>>、>、|
目录操作


ls、cp、mv、rm
ln、ln –s、chmod、groupadd、useradd
head、 tail、 grep、sort、sed、awk
其他
find、expr
 获取信息: man

Shell简介



shell是用户和内核之间的接口。为屏蔽内核复杂性,在内核周
围建一个外壳(shell),用户向shell提出请求,shell将请求
传给内核。Shell有多种,一般使用bash(bonurne shell)。
Shell是一种命令解释器,支持变量、函数、控制语句等,类似
于一种高级编程语言。
以#!/bin/sh开头,指示所用的命令解释器,#后接注释
为什么要有shell脚本

系统管理员每天需要进行大量且重复的管理工作
,如文件路径备份、更新等。这时候可以将重复
进行的操作写入一个文本文件,作为shell脚本运
行。
如,系统管理员每天都需要运行如下命令
groupadd groupname
usradd –m username1 -g groupname
usradd –m username2 –g groupname
-m默认方式,/home/username1

Shell脚本运行过程

编写shell脚本




使用任意编辑器(gedit、vim、nano等)编写脚本
添加执行权限: chmod u+x test.sh
运行脚本:
./test.sh
运行脚本的几种方式
 sh 脚本名:sh 只执行bash,读文件,只需r权限;开启新的儿子
shell运行脚本

./脚本名 :当前目录下该脚本,作为可执行程序运行,需x权限,每
次开启新的儿子shell运行脚本

. 脚本名:. 是一个命令,不开启儿子shell,当前shell运行
Vim编辑器

三种模式



插入模式: 键盘按键当作文本
命令模式: 键盘按键当作命令
底行模式: 输入“:” 进入。

另存为
:w 新文件名
保存退出 :wq

不保存退出:q!

Shell脚本示例
#!/bin/sh
#This is s1
sudo groupadd g1
sudo usradd –m u1 –g g1
sudo usradd –m u2 -g g1
chmod u+x s1
./s2
/etc/group查看组
/etc/passwd查看用户
Shell脚本示例
#!/bin/sh
#This is s2
#print “Hello Shell!”
echo “Hello Shell!”
chmod u+x s2
./s2
Shell的变量

变量名=变量值




不需要声明类型,直接赋值使用
等号后无空格,若变量值中有空格,需要引号,如
a=“hello world”
都为字符串类型,数值运算需要外部命令,expr
变量取值:在变量名称前加“$”






双引号“”:可引用除$、`、\外任意字符或字符串
单引号‘’:可引用引号里所有字符(包括引号)
$ A=a
$ echo $A
输出结果为 a
$ echo “$A”
输出结果为 a
$ echo ‘$A’ 输出结果为 $A
系统变量和特殊变量

系统变量



env命令查看所有环境变量
$HOME 用户主目录,~
$PATH 执行命令时所搜寻的目录
特殊变量

$0 这个程序的执行名字
$n 这个程序的第n个参数值
$* 这个程序的所有参数
$# 这个程序的参数个数
$$ 这个进程的PID
$? 执行上一个指令的返回值
test.sh:
#!/bin/sh
echo Filename: $0
echo Arguments: $*
echo Number of args.: $#
echo 1st arg.: $1
echo 2nd arg.: $2
执行: ./test.sh 1 2
条件测试

测试文件状态
-d:目录
-s:文件非空
-f:正规文件
-w:可写
-L:符号链接
-u:文件有suid位
-r:可读
-x:可执行

表达式
-eq
-ne
-gt
-lt
-n
-z
-le
-ge
=
!=
>
<
非空串
空串
<=
>=
# [ -f /etc/passwd -a -f /etc/inittab ]
# echo $?
0
# [ -x /etc/passwd -o -x /bin/sh ]
# echo $?
0
逻辑操作
-a &&
-o ||
!

控制语句

if 语句
if [条件测试 ]
then action
elif [条件]
then action
else action
fi
#!/bin/sh
scores=40;
if [ $scores -gt 90 ]
then echo "very good!"
elif [ $scores -gt 80 ]
then echo "good!"
elif [ $scores -gt 60 ]
then echo "pass!"
else
echo "no pass!"
fi
循环语句

for循环:

while循环:
for var in [list]
while [condition]
do
do
commands...
commands...
done
done
#!/bin/sh
number=1
while [ $number -le 10 ]
do
useradd user$number
echo Add a user whose name is:user$number
number=`expr $number + 1`
done
进程通信

进程间通信的作用
进程间需要数据传输、资源共享和事件通知。

进程间通信的方式
管道通信(无名管道和命名管道)
信号通信
内存资源共享
消息队列
信号量
管道通信

管道是单向的、先进先出的,把一个进程的输出
和另一个进程的输入连接在一起。一个进程(写
进程)在管道的尾部写入数据,另一个进程(读
进程)在管道的头部读出数据。

管道包括无名管道和有名管道两种,前者用于父
子进程间通信,后者用于运行任意两进程通信。
无名管道

创建无名管道:pipe()



#include <unistd.h>
int pipe(int filedes[2]); 成功返回0,否则返回-1
filedes是两个文件描述符,filedis[0]为管道读端,
filedis[1]为管道写端
无名管道

读管道

使用读文件描述符fd[0] ,调用read( )系统调用。
#include <unistd.h>
ssize_t read(int fd,void *buf,size_t nbytes);

返回:读到的字节数,若已到文件尾为0,出错为-1。



写管道

使用写文件描述符fd[1],调用write( )系统调用。
#include <unistd.h>

ssize_t write(int fd,const void *buf,size_t nbytes);

返回:已写字节数,若出错为-1。

fork()

创建子进程

一个现有进程调用fork函数可以创建一个子进程。
fork函数被调用一次但返回两次。若在子进程中则返
回0,父进程中则返回子进程ID。
main()
{ int i=fork();
if(i != 0)
{ 父进程执行的程序段;}
else if (i != -1)
{ 子进程执行的程序段;}
父子进程都执行的程序段;
}
Wait()

阻塞自己,直到子进程死亡

进程调用wait(),立即阻塞自己,由wait自动分析是
否当前进程的某个子进程已经退出,如果让它找到了
这样一个已经变成僵尸的子进程,wait就会收集这个
子进程的信息,并把它彻底销毁后返回;如果没有找
到这样一个子进程,wait就会一直阻塞在这里,直到
有一个出现为止
无名管道

父进程写数据,子进程读数据


先调用pipe()创建一个管道用于父子进程间通信,再调
用fork()创建一个子进程,该子进程会继承父进程所创
建的管道。必须在系统调用fork()前调用pipe()。
之后如父进程关闭写端,子进程关闭读端,就可以实
现子进程向父进程发送消息。
管道
 pipe(fd) 创建一个管道(#include <unistd.h>),fd[0]为管道的
读端;fd[1]为管道的写端。管道可用来实现父进程与其子孙进
程之间的通信。管道以FIFO方式传送消息。 例:
 main()
 {
int x,fd[2];

char buf[30],s[30];

pipe(fd);
/*创建管道*/

while((x=fork())= = -1);
/*创建子进程失败时,循环*/

if(x = = 0)

{
sprintf(buf,“This is an example\n”);

close(fd[0]);

write(fd[1],buf,30); /*把buf中的字符写入管道*/

exit(0);
}

wait();

read(fd[0],s,30);
/*父进程读管道中的字符*/

printf(“%s”,s);
 }
Linux下c编程



运行c文件,hello.c为例
gcc 文件名
./ 运行程序


gcc hello.c 编译+链接,得到可执行文件a.out
gcc –o hello hello.c 编译+链接,得到可执行文件hello
C语言源程序
.c
编译器
gcc
可执行文件
实验:Shell编程与父子进程通信
作业

Shell编程


设计一个shell程序,添加一个新组为class1,然后添加
属于这个组的30个用户,用户名的形式为stdxx,其
中xx从01到30。
父子进程间管道通信

创建一个无名管道和子进程,子进程向父进程发送消
息(如”This message is sent from child process”)
,父进程在收到消息后能做出反应(打印出”the
parent process has received the message”和该消息
)