Linux 커널에서 FIFO, 파이프 및 유닉스 도메인 소켓이 같은 것입니까?


30

FIFO가 파이프라는 이름을 들었습니다. 그리고 그들은 정확히 같은 의미론을 가지고 있습니다. 반면에 유닉스 도메인 소켓은 파이프와 매우 유사하다고 생각합니다. 그래서 그들이 모두 리눅스 커널에서 동일한 구현을 참조하는지 궁금합니다. 어떤 생각?


아래 답변에서 나는 내 질문이 모호하고 답하기 어렵다는 것을 깨달았습니다. 아무도 커널에서 구현에 대한 많은 세부 사항을 알 수 없을 것입니다 (커널 개발자조차도). 누군가가 유닉스 도메인 소켓, 파이프 및 FIFO가 Linux에서 공유 메모리로 전송되는 데이터를 모두 버퍼링한다는 것을 확인할 수 있다면 내 질문이 해결되었습니다. 글쎄 ... 부분적으로 해결되었습니다.
Justin

FIFO = 명명 된 파이프! = 파이프. FIFO는 소켓 쌍처럼 양방향 일 수 있습니다. 일반 파이프는 단방향입니다. 모두 파일 인터페이스와 파일 시맨틱이 있습니다. 구현이 왜 중요합니까?
PSkocik

파이프는 원형 버퍼이며 STREAMS 시스템을 사용하면 공유 구현이 가능하지만 Linux는 기본적으로 STREAMS를 사용하지 않습니다. 나는 리눅스가 이러한 IPC 채널을 하드 코딩한다고 믿는다. 그래도 확인하고 싶지 않습니다. : D 왜 안 그래? 코드는 공개적으로 사용 가능합니다.
PSkocik

모두 동일한 구현을 공유하는 경우 효율성은 서로 비슷해야합니다. 그리고 나에게는 커널 코드를 이해하기가 너무 어렵다.
저스틴

답변:


35

UNIX 도메인 소켓과 FIFO는 구현의 일부를 공유 할 수 있지만 개념 상 매우 다릅니다. FIFO는 매우 낮은 수준에서 작동합니다. 한 프로세스는 파이프에 바이트를 쓰고 다른 프로세스는 파이프에서 읽습니다. UNIX 도메인 소켓은 TCP / IP 소켓과 동일한 동작을합니다.

소켓은 양방향이며 많은 프로세스에서 동시에 사용할 수 있습니다. 프로세스는 동일한 소켓에서 많은 연결을 허용하고 동시에 여러 클라이언트에 참석할 수 있습니다. 커널 은 매번 새로운 파일 디스크립터를 제공 connect(2)하거나 accept(2)소켓에서 호출됩니다. 패킷은 항상 올바른 프로세스로 진행됩니다.
FIFO에서는 불가능합니다. 양방향 통신을 위해서는 두 개의 FIFO가 필요하며 각 클라이언트마다 한 쌍의 FIFO가 필요합니다. 의사 소통하는 훨씬 더 원시적 인 방법이기 때문에 선택적인 방식으로 글을 쓰거나 읽는 방법은 없습니다.

익명 파이프와 FIFO는 매우 유사합니다. 차이점은 익명 파이프가 파일 시스템에 파일로 존재하지 않으므로 프로세스가 open(2)불가능하다는 것입니다. 다른 방법으로 공유하는 프로세스에서 사용됩니다. 프로세스가 FIFO를 연 다음 예를 들어 a를 수행 fork(2)하면 해당 자식은 파일 설명자와 그 중에서 파이프를 상속합니다.

UNIX 도메인 소켓, 익명 파이프 및 FIFO는 공유 메모리 세그먼트를 사용한다는 점에서 비슷합니다. 구현의 세부 사항은 시스템마다 다를 수 있지만 아이디어는 항상 동일합니다. 두 개의 개별 프로세스 메모리 매핑에 동일한 메모리 부분을 연결하여 데이터를 공유하도록하십시오
( 편집 : 그것을 구현하는 확실한 방법이지만 실제로 버퍼에서 커널 메모리를 사용하는 Linux에서 실제로 수행되는 방식이 아니라 아래 @ tjb63의 답변을 참조하십시오.
그런 다음 커널은 시스템 호출을 처리하고 메커니즘을 추상화합니다.


"UNIX 도메인 소켓과 FIFO는 구현의 일부를 공유 할 수 있습니다"... 요점은 "일부"입니다 ... 방금 제 질문이 모호하고 답하기가 어렵다는 것을 깨달았습니다. 아무도 커널에서 공유하는 부분 (커널 개발자에게도)에 대한 많은 세부 정보를 알 수 없었을 것입니다. 그럼에도 불구하고 누구나 유닉스 도메인 소켓, 파이프 및 FIFO가 Linux에서 공유 메모리로 전송되는 데이터를 모두 버퍼링하는지 확인할 수 있습니까? 확인되면 내 질문이 해결됩니다. 글쎄 ... 부분적으로 해결되었습니다.
저스틴

예, 커널이 관리하는 버퍼가 있습니다. 예를 들어, FIFO를 사용하면 yoou가 라이터를 죽일 수 있으며 독자는 라이터가 죽기 전에 파이프로 보낸 내용을 계속 읽을 수 있습니다. 소켓을 사용하면 연결된 프로토콜로 작동하기 때문에 조금 더 복잡합니다. 그러나 소켓에 int를 보낸 다음 보낸 사람 스택에서 int가 지워지도록 범위를 벗어나면 수신자는 여전히 읽을 수 있습니다. 따라서 어딘가에 버퍼가 분명히 있습니다.
lgeorget

댓글을 다시 읽고 여기에 확실하지 않은 경우 ... 아직 확실하지 않은 사항이 있으면 알려주세요.
lgeorget

귀하의 의견은 분명합니다.
저스틴

7

여기에 대한 좋은 토론이 있습니다 : http://www.slideshare.net/divyekapoor/linux-kernel-implementation-of-pipes-and-fifos

내가 볼 수있는 한 프리젠 테이션 슬라이드와 소스 @ http://lxr.free-electrons.com/source/fs/pipe.c-fifo 는 파이프 주위의 래퍼로 구현되며 파이프 자체는 pipefs 가상 파일 시스템을 통해 구현됩니다.

@lgeorget - 배관 파이프는 독자와 작가 사이의 버퍼에 대한 커널 메모리를 사용하도록 표시 - 그들은 같은 '공유 메모리'를 사용하지 않으며, 사용자와 커널 주소 공간 (예를 들어, 사이에 메모리를 복사 pipe_read통화 pipe_iov_copy_to_user, 어떤 통화 __copy_to_user_inatomic(또는 copy_to_user) . __copy_to_user_inatomic통화 copy_user_generic여러 ASM의 구현에있다.


4

"FIFO"와 " named pipe"는 동일하지만 쉘이 명령 행의 두 명령 사이에서 "pipe"(|)를 처리하는 방법과는 상당히 다릅니다.

명명 된 파이프 (FIFO)는 두 개의 프로그램이 공유하는 단일 "파일"입니다. 하나는 파일에 쓰고 다른 하나는 그 파일에서 읽습니다. 반면에 소켓은 두 "파일"사이의 "연결"입니다. 하나의 프로그램이 하나의 "파일"에 읽고 다른 프로그램은 다른 하나에 읽고 쓰는 다른 네트워크에 네트워크를 사용하고 다른 컴퓨터에 읽습니다. 소켓, 명명 된 파이프 (파일, 장치, 심볼릭 링크)는 모두 inode를 사용하며 모두 공통 기능 (읽기 및 쓰기)을 구현합니다.


1
예, Unix 도메인 소켓은 일종의 소켓이므로 API는 TCP 또는 UDP 등의 다른 소켓 API와 비슷합니다. 그러나 Unix 도메인 소켓은 "로컬"IPC로만 사용할 수 있습니다. 그리고 데이터를 전송하는 방식은 FIFO 및 파이프와 매우 유사합니다. 그래서 유닉스 도메인 소켓의 API는 동일한 구현을 캡슐화 한 또 다른 것일 수 있으므로 소켓처럼 사용합니다. 나는 그들이 커널에서 모두 동일한 내부 를 공유 할 수 있다고 생각합니다 ... 그것이 사실인지 확인하고 싶습니다.
Justin

1

저스틴은 그렇게 생각하지 않습니다. 내가 실수하지 않았고 아마도 FIFO가 디스크의 파일을 사용하고 Unix Domain 소켓이 커널 메모리를 사용한다고 생각합니다.

또한 Unix 도메인 소켓이 양방향이라고 언급 한 위의 포스터 외에도 SOCK_STREAM 소켓을 사용할 때만 해당됩니다. SOCK_DGRAM Unix 도메인 소켓은 실제로 단방향이며 connect ()를 호출 한 코드에서 bind ()를 호출 한 코드로만 send ()를 보낼 수 있습니다.

물론 connect ()라는 코드는 bind ()를 호출하여 자체 끝점을 만들어야하지만 질문과는 관련이 없습니다.


3
StackExchange에 오신 것을 환영합니다. 게시 해 주셔서 감사합니다. 몇 가지주의 사항 ... 1) "아마도"잘못 알고 있다면 대답하기 전에 다시 한 번 확인해야합니다. 이 사이트는 포럼이나 채팅이 아닙니다. 2) 데이터 그램 지향 소켓에 대한 정확성에 감사드립니다. 3) 질문과 관련이없는 내용을 게시 할 필요가 없습니다. :)
lgeorget

1

내 2 센트 ... FIFO와 UNIX 소켓은 양방향 (유사한)이지만 소켓에는 스타 토폴로지가 있지만 FIFO는 대기열이므로 서로를 대체 할 수는 없습니다. 그렇습니다. 구현은 내부적으로 코드를 공유 할 수 있습니다.

**

char * myfifo = "/tmp/myfifo";
mkfifo(myfifo, 0666);
fd = open(myfifo, O_RDWR);   //so that you can read/write to it
 ...
write(fd, buff1, sizeof(buff1));  
getchar();//wait till some one reds this and writes something else
int sz=read(fd, buff1, sizeof(buff1));  //read that something**

FIFO는 양방향입니까?
jhfrontz
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.