06Shell并发控制

并发控制

文件描述

文件句柄

File Descriptors (FD,文件描述符)或 文件句柄:
进程使用文件描述符来管理打开的文件

注意

1.如何通过exec打开一个文件
exec 数字<> 文件名称
数字:/proc/$$/fd中未出现的数字
文件名称:相对路径或者绝对路径

2.如何通过exec关闭一个文件(释放文件句柄)
exec 数字<&-

3.当一个文件FD没有被释放,删除原文件也不会影响FD

示例说明

[root@hadoop04 ~]# ll /proc/$$/fd
total 0
lrwx------. 1 root root 64 Dec 10 09:18 0 -> /dev/pts/4
lrwx------. 1 root root 64 Dec 10 09:18 1 -> /dev/pts/4
lrwx------. 1 root root 64 Dec 10 09:18 2 -> /dev/pts/4
lrwx------. 1 root root 64 Dec 10 15:21 255 -> /dev/pts/4
[root@hadoop04 ~]# touch file1
# 打开文件
# exec 数字<> 文件名称
# 数字:/proc/$$/fd中未出现的数字
# 文件名称:相对路径或者绝对路径
[root@hadoop04 ~]# exec 6<> file1
[root@hadoop04 ~]# ll /proc/$$/fd
total 0
lrwx------. 1 root root 64 Dec 10 09:18 0 -> /dev/pts/4
lrwx------. 1 root root 64 Dec 10 09:18 1 -> /dev/pts/4
lrwx------. 1 root root 64 Dec 10 09:18 2 -> /dev/pts/4
lrwx------. 1 root root 64 Dec 10 15:21 255 -> /dev/pts/4
lrwx------. 1 root root 64 Dec 10 09:18 6 -> /root/file1


# 编辑文件
[root@hadoop04 ~]# echo "1111" >> /proc/$$/fd/6
[root@hadoop04 ~]# cat /proc/$$/fd/6
1111
[root@hadoop04 ~]# cat /root/file1
1111


# 删除文件、恢复文件
# 注意:即使恢复了file1文件,但是 `6 -> /root/file1 (deleted)`,原因是前后的file1的inode不一样
# 一个文件的句柄/描述符没有被释放,即使删除了文件,文件描述符依然在
[root@hadoop04 ~]# rm -rf /root/file1
[root@hadoop04 ~]# ll /proc/$$/fd
total 0
lrwx------. 1 root root 64 Dec 10 09:18 0 -> /dev/pts/4
lrwx------. 1 root root 64 Dec 10 09:18 1 -> /dev/pts/4
lrwx------. 1 root root 64 Dec 10 09:18 2 -> /dev/pts/4
lrwx------. 1 root root 64 Dec 10 15:21 255 -> /dev/pts/4
lrwx------. 1 root root 64 Dec 10 09:18 6 -> /root/file1 (deleted)
[root@hadoop04 ~]# cat /proc/$$/fd/6
1111
[root@hadoop04 ~]# cp /proc/$$/fd/6 /root/file1
[root@hadoop04 ~]# cat /root/file1
1111

# 释放文件句柄
# exec 数字<&-
[root@hadoop04 ~]# exec 6<&-   // 关闭当前进程的文件句柄6
[root@hadoop04 ~]# ll /proc/$$/fd
total 0
lrwx------. 1 root root 64 Dec 10 09:18 0 -> /dev/pts/4
lrwx------. 1 root root 64 Dec 10 09:18 1 -> /dev/pts/4
lrwx------. 1 root root 64 Dec 10 09:18 2 -> /dev/pts/4
lrwx------. 1 root root 64 Dec 10 15:21 255 -> /dev/pts/4

管道

管道本身就是文件

匿名管道

[root@hadoop04 ~]# rpm -qa | grep bash

命名管道

先进先出,取出了就没有了

[root@hadoop04 ~]# mkfifo /tmp/tmpfifo
[root@hadoop04 ~]# file /tmp/tmpfifo
/tmp/tmpfifo: fifo (named pipe)
[root@hadoop04 ~]# tty
/dev/pts/4

#打开两个终端
#终端1
[root@hadoop04 ~]# ll /dev  > /tmp/tmpfifo
#终端2
[root@hadoop04 ~]# grep 'sda' /tmp/tmpfifo 
brw-rw----. 1 root disk      8,   0 Dec  7 12:23 sda
brw-rw----. 1 root disk      8,   1 Dec  7 12:23 sda1
brw-rw----. 1 root disk      8,   2 Dec  7 12:23 sda2

并发控制案例

并发ping主机:通过命名管道和文件描述符实现多进程

[root@hadoop04 shell_concurrency_control]# vim ping_multi_thread01.sh
#!/usr/bin/bash
##########################################
# ping hosts mutil thread                #
# v1.1 by ElegantSmile 10/12/2019        #
##########################################

#进程数量
thread=5
#命名管道
tmp_fifofile=/tmp/$$.fifo

mkfifo ${tmp_fifofile}

exec 8<> ${tmp_fifofile}

rm ${tmp_fifofile}

for i in `seq ${thread}`
do
        # 操作文件描述8
        # &8表示文件描述8
        # 此处给文件描述8输入了5个回车,代表了5行内容
        echo >&8
done

for i in {1..254}
do
        # read -u fd
        # read -u选项可以跟上文件描述符
        read -u 8
        # 读取文件描述符8中的内容,读到一行就开启一个后台进程
        {
        ip=172.22.23.${i}
        ping -c1 -W1 ${ip} &> /dev/null
        if [ $? -eq 0 ] ;then
                echo "${ip} is up"
        fi
        # 每次执行完上面的循环体,就往文件描述8输入了1个回车
        # 因为在read -u 8的时候读取一行就少一行,当文件描述符8的内容为空,read -u 8就再也无法读取到内容,循环就会卡在那,所以此处要每次补充一行
        echo >&8
        }&
done

wait

# 可以通过读或者写的方式关闭文件句柄
#exec 8<&-
exec 8>&-

echo "all ok..."
原文地址:https://www.cnblogs.com/ElegantSmile/p/12056495.html