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時間を消費します。または、1つしかない場合は、バイトが利用可能になるまで読み取りが再びブロックされます。シンボリックリンクにリダイレクトする場合、バッファより少なく満たされると、読み込みはバッファを取得し、再び続行されます。 -> 。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

おすすめ記事