2010-12-22 2 views
2

현재 클라이언트 프로세스와 서버 프로세스가 있습니다. 클라이언트 프로세스는 데이터를 교환 할 때마다 서버 프로세스에 접속해야하지만 그렇게하기 위해 서버의 PID를 알아야합니다. 고객은 어떻게해야하는지 알고 있어야합니까? 반복되는 하드 디스크 액세스를 피하고 싶습니다. 이 응용 프로그램은 리눅스에서만 실행됩니다. 현재 서버는 pid 또는 RAM 디스크가있는 잠금 파일을 설정합니다. 클라이언트가 파일을 검사합니다. 다른 방법으로이 트랜잭션을 효율적으로 수행하여 서버가 클라이언트에 신호를 보낼 수 있습니까? (참고 : 클라이언트가 PHP이며, 서버는 c)간단한 리눅스 IPC 질문

+0

나는 다른 사람들이 제안한 것처럼이 전체적인 문제를 잘못 접근하고 있었다. 그러나 나는 그 때하고 싶은 일을 정확하게 수행하는 접근법이 존재한다./dev/shm에 자주 마운트되는 tmpfs 파일 시스템입니다.배포판에서 100 % 이식 할 수는 없지만 상당히 표준적인 것처럼 보입니다. – conartist6

답변

3

몇 가지 아이디어 : 아무것도하지

  1. ; 반복해서 읽으면 파일이 이미 캐시에 저장되어 있기 때문에 적절한 (영구적 인 디스크에있는) 디스크 파일을 읽는 것이 IO를 발생시키지 않습니다.
  2. 시스템을 리 팩터링하여 pid 파일을 알 필요가 없습니다.
  3. 정말로 신경 써야합니까? 조기 최적화와 그 모든 것. 1000 번 이상이 초당 몇 번이나하고 있습니까?
1

을 몇 가지 다른 옵션은 다음과 같습니다

  1. 특정 포트에서 수신하도록 서버를 설정합니다.
  2. 서버가 명명 된 파이프를 설정할 수 있으며 클라이언트가이를 통해 통신 할 수 있습니다.
+0

아무도 내 질문에 답하고 있지 않습니다. 제 질문은 IPC에 관한 것이 아닙니다. 그것은 IPC와 동기화에 관한 것입니다. 이미 클라이언트와 서버가 명명 된 파이프를 통해 통신하도록했습니다. 문제는 서버가 파이프를 청취 할시기를 알아야하는 방법입니다. 지금은 신호로 성취됩니다 (따라서 서버의 PID를 알아내어 정보에 반복적으로 액세스하여 스팸 디스크를 읽지 못하게하는 문제). 동기화를 시도하는 대신 서버는 다른 작업을 수행하지 않을 때마다 파이프에서 클라이언트 통신을 수신 대기해야한다고 말하고 있습니까? – conartist6

0
  • 유닉스 도메인 소켓
  • D-Bus
3

는 "프로세스"를 말할 때 나는 가정이 두 동일한 시스템에? 그렇다면 /tmp 디렉토리에서 명명 된 FIFO를 사용할 수 있습니다. 이 fork()로 명명 된 FIFO /tmp/test.fifo와 IPC를 사용하여 두 프로세스의 예입니다

#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; 
} 

그래서 한 두 프로세스는 FIFO의 전체 경로를 알고, 그들이 읽고 쓸 수 있습니다.

+0

이것은 내가 이미 진행 한 작업이지만 동기화 문제입니다. 현재 나의 셋업은 클라이언트 시그널 서버에 트랜잭션 준비가되어 있고, 트랜잭션은 서버의 시그널 핸들러 함수 내에서 발생한다. 어느 pid가 신호를 보낼지 어떻게 알 수 있습니까? – conartist6

+0

PID를 알 필요가 없습니다. 클라이언트가 FIFO를 읽는지를 알아야합니다. 이렇게하는 방법이 있습니다. 나는 확실하지 않다. 나는 서버가 읽기 전용으로 열릴 때까지 FIFO에 쓸 때 차단 될 것이라고 생각한다. 특정 인수 (예 : 서버가 차단하지 않음을 의미)로 FIFO를 만들 수 있지만 읽지 않는 경우 서버는 SIGPIPE 신호를받습니다. 이게 도움이 되길 바란다. – Doddy

2

일반적으로 pid를 사용하지 않고 IP 주소 (포트 포함), Unix 도메인 소켓 주소, 파일 시스템의 경로 또는 위에 빌드 된 일부 상위 IPC 시스템 이 중 하나 (D-Bus, X 등)를 사용하여 서버에 접속하고 서버와 통신하십시오. pid가 유용 할 수있는 유일한 방법은 신호를 보내는 것입니다.이 신호는 아마도 통신하기에 좋지 않은 방법 일 수 있으며 클라이언트와 서버를 별도의 권한 도메인으로 분리하면 작동하지 않습니다.

+0

좋아, 좋아, 좋아, 나는 그 소리가 마음에 든다. 그리고 나는 이미 prives를 얻기 위해 불쾌한 일을해야만했다. 그러나 이것을 구현하면 내 서버가 클라이언트가 무언가를 요청했을 때 어떻게 알 수 있을까? * 대부분의 경우 한 가지 작업 (클라이언트에 대한 데이터 수집)을 수행하고 클라이언트가 전송해야한다고 요구할 때 필요합니다. 지금 신호 처리기는 신호가 들어올 때 비동기 적으로 코드를 실행할 수있게 해줍니다. 그러나 소켓을 사용하면 소켓에 대한 일종의 이벤트 처리기를 설정할 수 있습니까? 내가 포크를하고 하나의 지점에서 루프를 듣는 루프를해야합니까? – conartist6

+0

두 가지 일반적인 접근 방법이 있습니다. 하나는'select' (또는'poll')를 사용하여 여러 파일 디스크립터 중 하나로부터 입력을 기다리는 이벤트 루프로 서버를 구성하는 것입니다. 또한 버퍼에서 출력을 쓰는 기능을 기다릴 수도 있습니다. 다른 하나는 쓰레드를 사용하거나 각각 IO를 차단하는 프로세스를 분리하는 것입니다. 하지만 프로세스를 사용한다면, 의사 소통을하고'select '에서 다시 끝내는 방법에 문제가 생길 것이다. 그래서 나는 처음에는'select' 루프를 사용하거나 스레드 (조건 변수와 장벽과 같은 pthread 프리미티브와 통신)를 사용합니다. –

0

non_blocking 모드에서 이름 IPC 메시지 대기열을 사용할 수 있다고 생각합니다. 명명 된 파이프가 non_blocking 모드를 지원하는지 여부는 모르지만, 그렇다면 사용할 수도 있습니다. non_block 모드에서는 신호 대기열 설명자를 등록하고 일반 대기 모드로 전환합니다. 대기열에 활동이 있으면 프로세스가 깨어납니다. 인터넷을 통해 몇 가지 검색을 해보세요. 같은 일을하는 많은 예를 찾을 수 있습니다.

정확하고 정확한 답변을 제공하려면 서버 프로세스 디자인을 알고 있어야합니다.