2010-08-15 3 views
8

직렬 장치 (/ dev/ttyXX)에서 하나 이상의 프로세스 읽기를 수행하면 두 프로세스 모두 모든 데이터를 가져올 수 없으므로 데이터가 어떤 방식 으로든 이들간에 분할됩니다. 직렬 장치에서 읽는 프로그램을 작성하고 여러 마스터/슬레이브 쌍을 작성한 다음 직렬 장치에서 읽도록 만든 프로그램이 ptys에서 읽도록하여 모든 읽기 프로세스가 데이터를 수신하도록 허용하고 싶습니다. 직렬 장치에서 pty가 직렬 장치처럼 작동하도록하십시오. pty에서 읽기 시작하면 최신 데이터 만 가져옵니다. 다른 말로하면, 읽기 시작하기 전에 작성된 데이터를 얻지 못할 것입니다 (이것이/dev/ttyXX 장치가 작동하는 방법 또는 적어도 읽는 RS-232 풍력계). 명명 된 파이프는 판독기가 없다는 것을 확인하기 위해 SIGPIPE를 트래핑하여 이러한 의미를 모방 할 수 있으므로 특정 명명 된 파이프에 쓰지 않도록 선택할 수 있습니다. 그러나 터미널을 사용하기 위해 작성된 일부 바이너리는 isatty()에 대한 검사와 tcsetattr()과 같은 호출에 대한 errno 조건이 실패 조건을 유발할 수 있으므로 명명 된 파이프와 통신 할 때 실패 할 수 있습니다. 여기서 핵심은 터미널 용으로 작성된 기존 바이너리를 사용할 수 있다는 것입니다.누군가 Linux에서 pty (의사 터미널)의 슬레이브 측을 열 때 어떻게 감지 할 수 있습니까?

그렇기 때문에 pty의 슬레이브 측이 읽기 위해 열렸을 때이를 감지 할 수 있다면 명명 된 파이프 케이스에 SIGPIPE가없는 것과 거의 동일한 의미를 갖습니다. HP-UX에는 TIOCTRAP이 ioctl() 명령으로있어 원하는대로 작동하는 것으로 보이지만 슬프게도 Linux에서는 사용할 수 없습니다.

필자는 며칠 동안 참고 문헌을 읽었으며이 유형의 옵션은 엄청나게 많습니다. 대답은 터미널 설정, 블로킹/블로킹 동작, 어딘가에 버퍼 크기 설정, poll()/select() 또는 일부 조합에서보고 된 조건에있을 수 있습니다. 그래도 나는 아무것도 찾을 수없는 것 같습니다. 나 자신의 장치 드라이버를 작성해야 할 가능성이 있는지 궁금하지만, 그렇게하지 않으면이 작업을 수행 할 수 있어야합니다.

따라서 설명을 위해 :
- 질문 : 누군가가 Linux에서 pty (의사 터미널)의 슬레이브 쪽을 열 때 어떻게 감지 할 수 있습니까?
- 독자가 pty의 슬레이브 측을 열면 리더가 pty를 연 후 엄격하게 쓰여진 데이터를 수신하게합니다. (필자의 다중 쓰기 프로세스가 단지 데이터를 쓰는 동안 리더가 슬레이브 측을 열면 데이터가 버퍼링됩니다. 결과적으로 필자는 차단하고 슬레이브 리더는 즉시 모든 버퍼링 된 데이터를 가져옵니다. 즉, 즉각적인 임시 주변에서 생성 된 데이터 만 가져 오려면 바람직하지 않습니다.
- isatty() 및 tcsetattr()과 같이 이름이 지정된 파이프, 소켓 등이 아닌 pty 일 수 있습니다. 기존 바이너리가 작동 할 수 있도록 확인해야합니다.

답변

9

찾을 수없는 이유는 문서화되어 있지 않기 때문입니다. 인터페이스 지정 ically 그것을 허용합니다. 그러나, 당신이 그것을 할 수있는 트릭이 있습니다.

close(open(ptsname(ptm), O_RDWR | O_NOCTTY)); 

이것은 TTY 마스터에 HUP 플래그를 설정 의사 단말 마스터 개봉 후 열려 즉시 슬레이브 측을 닫고 (파일 디스크립터 ptm 것으로 가정하에). (데이터가 데이터 소스에서 들어오는 때마다 말) 이제 poll()와 함께 정기적으로 HUP 플래그를 폴링 : 독자가 지금까지 사라질

struct pollfd pfd = { .fd = ptm, .events = POLLHUP }; 
poll(&pfd, 1, 10 /* or other small timeout */); 

if (!(pfd.revents & POLLHUP)) 
{ 
    /* There is now a reader on the slave side */ 
} 

경우, POLLHUP이 다시 설정됩니다.

귀하의 데이터 소스에 read() 블록이 있고 데이터가 사용 가능할 때 동시에 차단되는 특정 pty에 한 루프에서 다음 루프까지 기억할 필요조차 없습니다. poll() 모두 당신의 주인은 POLLHUP이없는 그들 중 누구에게나 데이터를 보내라.

+0

설명해 주셔서 감사합니다. 소스 코드에서 "socat"이라는 트릭을 발견했지만 슬레이브 측을 열고 닫아야 만한다는 것을 깨닫지 못했습니다. 트릭을 이해 한 후에도 명시 적으로/dev/ptmx를 열지 않고 openpty()를 사용했기 때문에 머리카락을 잡아 당기는 에피소드가 있었지만 pts에 대해 별도의 열린 fd를 제공하여 HUP 조건을 얻을 수 없었습니다 처음에는 openpty()를 호출하고 그로부터 리턴 된 슬레이브 fd를 닫는 것으로 충분하다. 응답에 다시 한 번 감사드립니다. 문서화되지 않은 기능에 대해 어떻게 알게 되었습니까? –

+0

유즈넷에 글을 올리는 것으로 방금 발견했다고 생각합니다. 이 질문은 미래의 사람들을 위해 더 많은 Google 기능을 제공 할 것입니다. – caf

3

슬레이브 pty에 inotify watch를 추가하고 그것에 대해 조사하십시오. inotify 이벤트를 열어 볼 수 있습니다. 그런 다음 inotify 파일 설명자와 마스터 pty 파일 설명자를 폴링 할 수 있습니다. open (IN_OPEN)에 대한 inotify 이벤트를 얻을 수 있습니다. 그러면 슬레이브 측이 열릴 때 폴링이 차단됩니다.

관련 문제