• unix 管道通信接口


     

     1.接口声明参照python connection

     2.不好的地方:

      2.1 权限设置没有linux 读写执行按位&那样优美,健壮

      2.2 用特化实现重载send,recive,比较别扭。更自然一点是根据模版参数,决定是否声明send,recive。

        尝试使用std::enable_if, std::integral_constant, std::is_name组合达到上面的目的,但是失败了。

        期待找到类似"declare_if(static_bool) void fun() "的东西。

      1 #ifndef DUMP_CONNECTION_PIPE_H
      2 #define DUMP_CONNECTION_PIPE_H
      3 
      4 #include <type_traits>
      5 #include <unistd.h>
      6 #include <stdint.h>
      7 #include <string.h>
      8 #include <stdio.h>
      9 #include <stdlib.h>
     10 
     11 
     12 enum ConnPermission {
     13     CONN_READABLE = 1,
     14     CONN_WRITABLE = 2
     15 };
     16 
     17 template<ConnPermission permission>
     18 class ConnectionPipe
     19 {
     20 private:
     21     //use for multi process atomic write one pipe
     22     #pragma pack(1)
     23     struct AtomicPipeData {
     24         static const size_t max_cap = 256;
     25         char data[max_cap];
     26         uint16_t size:14;
     27         uint16_t status:2; //1 is sending, 0 is end
     28         //uint64_t id; use for package join to msg
     29     };
     30     #pragma pack()
     31 public:
     32     explicit ConnectionPipe(int fd) : fd_(fd){}
     33     ConnectionPipe(const ConnectionPipe&) = delete;
     34     ConnectionPipe& operator=(const ConnectionPipe&) = delete;
     35     ~ConnectionPipe() = default;
     36 
     37     void Close(){
     38         close(fd_);
     39     }
     40 
     41     int FileNo() const {
     42         return fd_;
     43     }
     44 
     45     //bool Poll();
     46 
     47     //int Recv();
     48     char* RecvBytes(size_t* msg_len);
     49 
     50     //int RecvBytesInto();
     51     //bool Send();
     52     bool SendBytes(const char* msg, size_t msg_len);
     53 private:
     54     int fd_;
     55 };
     56 
     57 template<>
     58 char* ConnectionPipe<CONN_READABLE>::RecvBytes(size_t* msg_len) {
     59     if (msg_len == nullptr) {
     60         return nullptr;
     61     }
     62 
     63     int nreaded = 0;
     64     AtomicPipeData buf = {0};
     65     size_t msg_cap = AtomicPipeData::max_cap * 16; //4096 one page
     66     char * msg = new char[msg_cap];
     67     size_t msg_offset = 0;
     68     auto resize_mgs = [&msg, &msg_cap, &msg_offset](){
     69         size_t recommended_cap = msg_cap * 2;
     70         char* new_msg = new char[recommended_cap];
     71         memset(new_msg, 0, recommended_cap);
     72         memcpy(new_msg, msg, msg_offset);
     73         delete[] msg;
     74         msg = new_msg;
     75         msg_cap = recommended_cap;
     76     };
     77 
     78     while (1) {
     79         int nread = read(fd_, (char*)&buf + nreaded, sizeof(buf) - nreaded);
     80         {
     81             if (nread == -1) {
     82                 perror("read");
     83                 exit(EXIT_FAILURE);
     84             }
     85             //child close write pipe
     86             if (nread == 0) break;
     87         }
     88 
     89         nreaded += nread;
     90         if (nreaded == sizeof(buf)) {
     91             if ((msg_offset + buf.size) > msg_cap) {
     92                 resize_mgs();
     93             }
     94 
     95             memcpy(msg + msg_offset, buf.data, buf.size);
     96             msg_offset += buf.size;
     97 
     98             //use for ending package buf of one message
     99             if (buf.status == 0) {
    100                 break;
    101             }
    102 
    103             //use for loop next step read
    104             nreaded = 0;
    105             memset(&buf, 0, sizeof(buf));
    106         }
    107     };
    108 
    109     *msg_len = msg_offset;
    110     return msg;
    111 }
    112 
    113 template<>
    114 char* ConnectionPipe<CONN_WRITABLE>::RecvBytes(size_t* msg_len) {
    115     return nullptr;
    116 }
    117 
    118 template<>
    119 bool ConnectionPipe<CONN_WRITABLE>::SendBytes(const char* msg, size_t msg_len) {
    120     if (msg == nullptr || msg_len == 0) {
    121         return false;
    122     }
    123 
    124     AtomicPipeData package;
    125     auto fill_package = [&package](const char * data, uint16_t len, uint16_t status) {
    126         memset(&package, 0, sizeof(package));
    127         memcpy(package.data, data, len);
    128         package.size = len;
    129         package.status = status;
    130     };
    131 
    132     const size_t packages_size = (msg_len + AtomicPipeData::max_cap - 1)/AtomicPipeData::max_cap;
    133     for (size_t i = 0; i < packages_size; ++i) {
    134         size_t offset = i * AtomicPipeData::max_cap;
    135         if (i != packages_size - 1) {
    136             fill_package(msg+offset, AtomicPipeData::max_cap, 1);
    137         }
    138         else {
    139             fill_package(msg+offset, msg_len - offset, 0);
    140         }
    141 
    142         if (write(fd_, &package, sizeof(package)) != sizeof(package)) {
    143             /* Nothing to do on error, this will be detected by the other side. */
    144         }
    145     }
    146 
    147     return true ;
    148 }
    149 
    150 template<>
    151 bool ConnectionPipe<CONN_READABLE>::SendBytes(const char* msg, size_t msg_len) {
    152     return false;
    153 }
    154 
    155 static bool NewConnPair(ConnectionPipe<CONN_WRITABLE>** pp_sender, ConnectionPipe<CONN_READABLE>** pp_receiver) {
    156     int pipedes[2];
    157     if (pipe(pipedes) == -1) {
    158         close(pipedes[0]);
    159         close(pipedes[1]);
    160         return false;
    161     }
    162 
    163     *pp_receiver = new ConnectionPipe<CONN_READABLE>(pipedes[0]);
    164     *pp_sender   = new ConnectionPipe<CONN_WRITABLE>(pipedes[1]);
    165 
    166 
    167     printf("pipe buffer size = %ld
    ", fpathconf(pipedes[0], _PC_PIPE_BUF));
    168     return true;
    169 }
    170 
    171 #endif
    172 
    173 
    174 int main()
    175 {
    176 
    177    ConnectionPipe<CONN_WRITABLE>* p_sender   = nullptr;
    178    ConnectionPipe<CONN_READABLE>* p_receiver = nullptr;
    179    if (!NewConnPair(&p_sender, &p_receiver)) {
    180         exit(EXIT_FAILURE);
    181    }
    182 
    183    std::shared_ptr<ConnectionPipe<CONN_WRITABLE>> sender_ptr(p_sender);
    184    std::shared_ptr<ConnectionPipe<CONN_READABLE>> receiver_ptr(p_receiver);
    185 
    186    pid_t regionid_pid = fork();
    187    if (regionid_pid == -1) {
    188        perror("fork");
    189        exit(EXIT_FAILURE);
    190    }
    191    else if (regionid_pid == 0) {
    192        //sub process
    193        receiver_ptr->Close();
    194        sender_ptr->SendBytes("bufff", 5);
    195        sender_ptr->Close();
    196        _exit(EXIT_SUCCESS);
    197    }
    198    else {
    199        //parent mian process
    200        sender_ptr->Close();
    201        size_t msg_len = 0;
    202        char* msg = receiver_ptr->RecvBytes(&msg_len);
    203        receiver_ptr->Close();
    204        waitpid(regionid_pid, NULL, 0);
    205    }
    206     
    207     return 0
    208 }
    209     

     

  • 相关阅读:
    std::copy、std_copy_if、std::copy_n
    std::mem_fn
    gitresolved
    基于多传感器融合的贵重物品定位管理物联网解决方案简析
    ADS1299开发调试总结之寄存器使用说明简析
    可穿戴心电ECG监测的技术路径及特点
    基于ADS1292芯片的解决方案之芯片简析
    动物生理信号遥测系统解决方案综述
    ubuntu16.04 关闭系统的屏幕阅读功能
    九轴加速度传感器的一些科普概念
  • 原文地址:https://www.cnblogs.com/water-bear/p/14951159.html
Copyright © 2020-2023  润新知