管道(),fork()和信号处理程序中的内存和管道/套接字管理

时间:2018-01-31 22:07:09

标签: c pipe signals fork posix

使用forkpipesignal.h信号处理。 STDIN用于快速模拟与网络服务器的套接字连接。伪代码:

struct message_t {
    uint32_t length;
    uint8_t *data;
};

int is_shutdown = 0;

void signal_handler(int) {
    //set is_shutdown if SIGINT
}

int main() {
    //initialize
    pipe();
    fork();

    if (parent) {
        while(!is_shutdown) {
            //0. initialize variables, buffer, message_t
            //1. read string of unknown length from STDIN (or socket) to a buffer
            //2. malloc() message_t and fill it's fields
            //3. write() message_t to pipe
            //4. free() message_t
        }
    }

    if (child) {
        while(!is_shutdown) {
            //0. initialize variables, message_t
            //1. read() message_t: read length, malloc() buffer, read data
            //2. execute command
            //4. free() message_t
        }   
    }

    //close pipe
}

有些让我困惑的事情:

  1. 我应该close()信号处理程序中的pipe吗?
  2. 我不完全理解在发送消息(父节点)后消息(它的内存)会发生什么。我应该在free()之后write()缓冲区吗?
  3. 如何处理来自信号处理程序的资源释放。我应该将缓冲区和fd作为全局变量来实现,以便从信号处理程序
  4. 访问它们
  5. is_shutdown标志和进程间通信。我是否理解父母和孩子不会将is_shutdown作为同一个变量(他们是副本)共享,而改变为另一个不会改变另一个?
  6. 对信号处理程序和is_shutdown的{​​{1}}进行并发访问怎么样?任何隐藏的细节,如通过多线程并发?
  7. 当一个进程关闭时,另一个进程仍然有效。如果管道出现问题,我将无法通知另一个。我希望有一个SIGPIPE吗?
  8. 我怀疑从性能角度来看,在父{q}}循环的每次迭代中调用main都不是明智之举。但是定义“足够大”的缓冲区感觉就像一个黑客(如果有一天它不够大的话)。我错了吗?
  9. 我对C及其内存和资源管理都很陌生:从基于强大的英特尔服务器/台式机的C ++ 14开发切换到~180MHz ARM嵌入式系统的C开发,所以我可能会担心很多而忘记一些明显的的东西。

1 个答案:

答案 0 :(得分:1)

  1. 不,你不应该。您应该在信号处理程序中执行的仅 事件设置为is_shutdown
  2. write制作副本。在write返回后,重用或取消分配缓冲区是安全的。 (但一定要处理短写。)
  3. 你不是。同样,您应该在信号处理程序中执行的事件设置为is_shutdown。在while循环终止后,在parentchild块中清理。
  4. 是的,每个流程都有一个独立的副本。您还应该知道,使用此设计,如果您从终端运行程序然后在其中键入^ C,内核将在两个进程上触发SIGINT,因为它们都在同一个进程组中。
  5. is_shutdown需要使用类型volatile sig_atomic_t声明,对于像这样的简单程序,它不应该被信号处理程序以外的任何东西写入。此外,信号处理程序不应读取其值,它应该只设置它。根据您尚未向我们展示的代码的详细信息,在不使用SA_RESTART的情况下安装信号处理程序可能是合适的,这样就可以中断阻塞系统调用。
  6. 您唯一需要做的就是确保通信通道的每一侧都能正常地处理另一端突然断开连接。
    • 如果这是最终将成为网络服务器和客户端的模型,您应该在开始测试突然断开连接之前从使用pipe更改为使用socketpair,因为socketpair fds表现得更像真正的网络套接字。
  7. I / O开销可能比malloc开销大得多。在这个阶段担心malloc开销是不成熟的优化。