zoukankan      html  css  js  c++  java
  • 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..."
    
  • 相关阅读:
    Effective C# 原则37:使用标准的配置机制(译)
    Effective C# 原则31:选择小而简单的函数(译)
    Effective C# 原则24:选择申明式编程而不是命令式编程(译)
    Effective C# 原则34:创建大容量的Web API(译)
    Effective C# 原则27:避免使用ICloneable(译)
    Effective C# 第4章:创建基于二进制的组件(译)
    Effective C# 原则39:使用.Net验证(译)
    Effective C# 原则35:选择重写函数而不是使用事件句柄(译)
    Effective C# 原则25: 让你的类型支持序列化(译)
    Effective C# 原则38:使用和支持数据绑定(译)
  • 原文地址:https://www.cnblogs.com/ElegantSmile/p/12056495.html
Copyright © 2011-2022 走看看