pts가 닫히면 read(2)의 차단 동작이 변경되어 read()가 오류: -1(EIO)을 반환하게 됩니다.

pts가 닫히면 read(2)의 차단 동작이 변경되어 read()가 오류: -1(EIO)을 반환하게 됩니다.

나는 내가 가지고 있는 pt 마스터를 통해 안정적으로 루프를 반복하는 방법을 찾으려고 노력 중입니다. 평소처럼 ptmx를 열고 권한을 부여하고 잠금을 해제합니다.

* ptmx stuff */
/* get the master (ptmx) */
int32_t masterfd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
if(masterfd < 0){
    perror("open");
    exit(EXIT_FAILURE);
};

/* grant access to the slave */
if(grantpt(masterfd) < 0){
    perror("grantpt");
    exit(EXIT_FAILURE);
};

/* unlock the slave */
if(unlockpt(masterfd) < 0){
    perror("unlockpt");
    exit(EXIT_FAILURE);
};

comms_in->ptmx = masterfd;

다음으로 슬레이브의 이름을 저장합니다(예, sizeof(char)는 항상 1이라는 것을 알고 있습니다).

/* get the path to the slave */
char * slavepathPtr;
char * slavePath;
size_t slavepathLen;
if((slavepathPtr = ptsname(masterfd)) == NULL){
    perror("ptsname");
    exit(EXIT_FAILURE);
}else{
    slavepathLen = strlen(slavepathPtr);
    slavePath = (char *) malloc(sizeof(char) * (slavepathLen + 1));
    strcpy(slavePath, slavepathPtr);
};

그런 다음 (getopts를 사용하여 해당 프로그램에 대한 인수로 제공되는) /dev/pts/number슬레이브( )에 대한 예측 가능한 이름의 심볼릭 링크를 생성하고 , 에 대한 호출을 사용하여 해당 권한이 안전한지 확인 하고 프로그램 이 계속 실행될 수 있는지 확인합니다. 심볼릭 링크를 걸어 스레드를 종료합니다./dev/custom/predictableaccesslstatreadlinksymlinkunlink

마지막으로 프로그램은 이 루프에 들어갑니다.

ssize_t read_result;
ssize_t write_result;
while(1){
    if((read_result = read(comms_in->ptmx, ptmxio_read_buffer, sizeof ptmxio_read_buffer)) <= 0){
        { /** calls thread ender routine */
            pthread_mutex_lock(&COMMS_MUTEX);
            comms_in->thread_statuses[PTMXIO_THREAD] = THREAD_FAILED;
            pthread_mutex_unlock(&COMMS_MUTEX);
            pthread_cond_signal(&SIG_PROGRAM_FINISHED);
            pthread_exit((void *) comms_in);
        }
    }else if((write_result = write(STDOUT_FILENO, ptmxio_read_buffer, read_result)) != read_result){
        {
            /** same as above */
        }
    };
};

시스템에서 이 프로그램을 실행할 수 있으며 모든 것이 정상입니다. 블록을 읽어보세요. cupts 심볼릭 링크를 사용하거나 열면 picocom내 측 또는 커널 측의 버퍼 제한 중 더 낮은 쪽까지 바이트가 성공적으로 읽혀집니다. 문제는 슬레이브가 종료될 때 발생합니다. 이 시점에서 읽기는 오류 텍스트와 함께 -1->를 반환하며 스레드와 루프를 종료하지 않기로 선택하면 계속해서 그렇게 하므로 많은 CPU 시간을 소비하게 됩니다. 또는 하나만 있는 경우 바이트 를 사용할 수 있을 때까지 읽기가 다시 차단됩니다. 심볼릭 링크로 리디렉션하는 경우 버퍼보다 ​​적게 채워지면 읽기는 버퍼를 가져오고 다시 계속 진행됩니다. -> .EIOInput/output errorcupicocomecho -en "some text" > /dev/pts/number-1EIO

어떻게 되어가나요? 느린 임베디드 애플리케이션 프로세서에서 실행되고 바이트 손실 없이 읽기를 다시 설정할 수 있도록 하기 때문에 CPU를 많이 사용하지 않는 방법이 필요합니다.

나는 이것을 호출하는 스레드를 발견했습니다. ioctl(3, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...})그리고 이 3가지 옵션이 내 Linux 헤더 어디에도 없었기 때문에 무엇인지 알 수 없었습니다. 이것은 / 3입니다 .comms_in->ptmxmasterfd

다음은 심볼릭 링크의 lstat와 몇 가지 추가 정보입니다. st_mode는 읽기 성공 및 실패 전후에 변경되지 않은 상태로 유지됩니다.

‘ptmxio_thread’ failed read (-1) on /dev/pts/13 /dev/pts/13: Input/output error
‘ptmxio_thread’ ptsNum (from ioctl) 13
‘ptmxio_thread’ st_dev: 6, st_ino: 451, st_mode: 0000A1FF, st_nlink: 1
‘ptmxio_thread’ st_uid: 000003E8, st_gid: 000003E8, st_rdev: 0, st_size: 11
‘ptmxio_thread’ st_blksize: 4096, st_blocks: 0, st_atime: 1540963806, st_mtime: 1540963798
‘ptmxio_thread’ st_ctime: 1540963798

답변1

매우 간단합니다. 마스터를 처리하는 프로그램에서 슬레이브에 대한 pty 핸들을 열고 열어 두어야 합니다.

이름을 얻으면 그것 ptsname(3)입니다 open(2).

나는 이것을 호출하는 스레드를 발견했습니다. ioctl(3, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...})그리고 이 3가지 옵션이 내 Linux 헤더 어디에도 없었기 때문에 무엇인지 알 수 없었습니다. 3임을 참고하시기 바랍니다 comms_in->ptmx / masterfd.

ioctl(TCGETS)예 , 및 tcgetattr(3)라고도 합니다 . 와 에 정의되어 있습니다 . 이는 이전 버전의 버그 때문입니다 .isatty(3)ptsname(3)/usr/include/asm-generic/ioctls.hSNDCTL*SNDRV*strace

int32_t masterfd = open("/dev/ptmx", O_RDWR | O_NOCTTY);

프로그램을 불필요하게 이식 불가능하게 만드는 것은 의미가 없습니다. 대신 사용하십시오 posix_openpt(3).

slavepathLen = strlen(slavepathPtr);
slavePath = (char *) malloc(sizeof(char) * (slavepathLen + 1));
strcpy(slavePath, slavepathPtr);

그게 strdup(3)목적이에요 ;-)

read()또한 신호에 의해 방해받는 것도 처리해야 합니다 .전적으로귀하(및 귀하가 호출하는 모든 라이브러리 함수)가 SA_RESTART.

관련 정보