Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
简单的Linux IPC问题_C_Linux_Ipc - Fatal编程技术网

简单的Linux IPC问题

简单的Linux IPC问题,c,linux,ipc,C,Linux,Ipc,目前我有一个客户端进程和一个服务器进程。客户机进程需要经常联系服务器进程以交换数据,但需要知道服务器的pid才能这样做。客户应该如何知道如何做到这一点?我想避免重复访问硬盘。此应用程序仅在linux下运行。目前,服务器设置了一个带有pid的锁文件,该pid是有效的,或者是一个RAM磁盘。客户端检查文件。我如何才能高效地完成此事务,以便服务器可以向客户端发送信号?(注意:客户端是PHP,服务器是c)其他一些选项包括: 将服务器设置为侦听特定端口 服务器可以设置一个命名管道,客户端可以通过该管道与之

目前我有一个客户端进程和一个服务器进程。客户机进程需要经常联系服务器进程以交换数据,但需要知道服务器的pid才能这样做。客户应该如何知道如何做到这一点?我想避免重复访问硬盘。此应用程序仅在linux下运行。目前,服务器设置了一个带有pid的锁文件,该pid是有效的,或者是一个RAM磁盘。客户端检查文件。我如何才能高效地完成此事务,以便服务器可以向客户端发送信号?(注意:客户端是PHP,服务器是c)

其他一些选项包括:

  • 将服务器设置为侦听特定端口
  • 服务器可以设置一个命名管道,客户端可以通过该管道与之通信
  • 一些想法:

  • 什么也不做;如果反复读取,读取光盘文件(在正确的永久光盘上)不会导致任何IO,因为该文件已在缓存中
  • 重构你的系统,这样你就不需要知道pid文件了
  • 你确定你真的在乎吗?过早的优化等等。你每秒做多少次,1000次或更多
    • Unix域套接字
      • 我想,当你说“过程”时,这两个在同一台机器上?如果是这样,您可以在
        /tmp
        目录中使用命名的FIFO。这是一个使用IPC的两个进程的示例,命名为FIFO
        /tmp/test.FIFO
        fork()

        #包括
        #包括
        #包括
        #包括
        #包括
        #包括
        #包括
        int errno;
        int main(int argc,字符**argv)
        {
        字符fifo_路径[]=“/tmp/test.fifo”;
        字符缓冲区[128];
        int result=mkfifo(fifo_路径,0600);
        printf(“mkfifo结果=%d\n”,结果);
        if(errno==EEXIST)
        printf(“errno==EEXIST\n”);
        pid_t child=fork();
        如果(子项==0)
        {
        printf(“%d>子级;打开fifo\%s\”进行写入\n“,getpid(),
        先进先出路径);
        文件*fifo=fopen(fifo_路径,“w”);
        缓冲区中的字符[128];
        fgets(在缓冲区中,128,标准输入);
        FPUT(在缓冲区中,fifo);
        fclose(先进先出);
        }
        其他的
        {
        printf(“%d>父级;打开fifo\%s\”进行读取\n“,getpid(),
        先进先出路径);
        文件*fifo=fopen(fifo_路径,“r”);
        FGET(缓冲器、128、fifo);
        if(缓冲区[0]==EOF)
        printf(“%d>获得EOF\n”,getpid());
        其他的
        {
        缓冲区[strlen(buffer)-1]=0;
        printf(“%d>读取字符串\%s\”\n),getpid(),buffer);
        }
        fclose(先进先出);
        }
        返回0;
        }
        

        因此,只要两个进程都知道FIFO的完整路径,它们就可以对其进行读取和写入。

        通常您不使用pid,而是使用某种类型的地址—IP地址(包括端口)、Unix域套接字地址、文件系统中的路径,或者在其中一个(D-Bus、X等)之上构建的某个更高级别的IPC系统到达服务器并与服务器通信。pid唯一有用的是发送一个信号,这可能是一种非常糟糕的通信方式,如果您将客户端和服务器分离到单独的特权域中,它将不起作用。

        我认为您可以在非阻塞模式下使用名称IPC消息队列。我不知道命名管道是否支持非阻塞模式,但如果是,您也可以使用它。在非块模式下,您只需注册队列描述符来发送信号,然后进入常规等待。如果队列上有任何活动,您的进程将被唤醒。请在互联网上做一些搜索,你可以找到许多这样做的例子


        要给出正确/准确的答案,我应该了解您的服务器进程设计。

        这是我已经做过的,但问题是同步。目前,我的设置是让客户端向服务器发送信号,表明它已准备好进行事务,然后事务在服务器中的信号处理程序函数中发生。它如何知道向哪个pid发送信号?您不需要知道pid;您只需要知道客户机是否正在读取FIFO。有一种方法可以做到这一点;不过我不确定。我相信服务器在写入FIFO时会阻塞,直到它被打开读取。您可以使用某些参数创建FIFO,这意味着服务器不会阻塞,但如果没有读取FIFO,服务器将接收SIGPPIPE信号。我希望这有帮助。所以。。。没有人回答我的问题。我的问题不完全是关于IPC的。它是关于IPC的同步。我已经让客户端和服务器通过命名管道进行通信。问题是服务器应该如何知道何时监听管道。现在,这是通过信号实现的(因此,需要知道服务器的pid并将其保存在重复访问信息不会导致垃圾邮件磁盘读取的地方)。你是说,服务器应该在不做任何其他事情的情况下,在管道上监听客户端的通信,而不是尝试同步吗?好的,好的,我喜欢这样的声音,我已经做了一些不愉快的事情来纠正privs,但是如果我实现了这一点,我的服务器如何知道客户机何时请求了什么?它大部分时间都需要做一件事(为客户机收集数据),然后当客户机要求它传输数据时。现在,一个信号处理程序允许我在收到信号时异步执行代码。但是有一个插座。。。我可以为套接字设置某种类型的事件处理程序吗?我应该分叉并让一个分支只循环监听套接字吗?有两种通用方法。一种是使用
        select
        (或
        poll
        )将服务器构造为一个事件循环,以等待来自多个文件描述符中任何一个的输入,还可能等待从缓冲区写入输出的能力。另一种是在IO中使用线程或单独的进程。但是,如果您使用流程,您将遇到一个问题,即如何使流程与用户进行通信
        #include <stdio.h>
        #include <string.h>
        #include <errno.h>
        #include <unistd.h>
        #include <sys/types.h>
        #include <sys/stat.h>
        #include <linux/stat.h>
        
        int errno;
        
        int main(int argc, char** argv)
        {
            char fifo_path[] = "/tmp/test.fifo";
            char buffer[128];
        
            int result = mkfifo(fifo_path, 0600);
        
            printf("mkfifo result = %d\n", result);
        
            if (errno == EEXIST)
                printf("errno == EEXIST\n");
        
            pid_t child = fork();
        
            if (child == 0)
            {
                printf("%d> child; opening fifo \"%s\" for writing\n", getpid(),
                         fifo_path);
        
                FILE* fifo = fopen(fifo_path, "w");
                char in_buffer[128];
        
                fgets(in_buffer, 128, stdin);
        
                fputs(in_buffer, fifo);
        
                fclose(fifo);
            }
            else
            {
                printf("%d> parent; opening fifo \"%s\" for reading\n", getpid(),
                         fifo_path);
        
                FILE* fifo = fopen(fifo_path, "r");
        
                fgets(buffer, 128, fifo);
        
                if (buffer[0] == EOF)
                    printf("%d> got EOF\n", getpid());
                else
                {
                    buffer[strlen(buffer) - 1] = 0;
                    printf("%d> read string \"%s\"\n", getpid(), buffer);
                }
        
                fclose(fifo);
            }
        
            return 0;
        }