4

私はなどについて読んEINTRwrite(2)いて、プログラムでそれをチェックする必要があるかどうかを判断しようとしています。健全性チェックとして、それに遭遇するプログラムを書こうとしました。プログラムは永久にループし、ファイルに繰り返し書き込みます。

次に、別のシェルで次のコマンドを実行します。

while true; do pkill -HUP test; done

ただし、test.cからの出力は.、シグナルハンドラーからのsだけです。なぜ失敗のSIGHUP原因にならないのですか?write(2)

test.c:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <errno.h>

#include <sys/types.h>

void hup_handler(int sig)
{
    printf(".");
    fflush(stdout);
}

int main()
{
    struct sigaction act;
    act.sa_handler = hup_handler;
    act.sa_flags = 0;
    sigemptyset(&act.sa_mask);

    sigaction(SIGHUP, &act, NULL);

    int fd = open("testfile", O_WRONLY);

    char* buf = malloc(1024*1024*128);

    for (;;)
    {
        if (lseek(fd, 0, SEEK_SET) == -1)
        {
            printf("lseek failed: %s\n", strerror(errno));
        }
        if (write(fd, buf, sizeof(buf)) != sizeof(buf))
        {
            printf("write failed: %s\n", strerror(errno));
        }
    }
}
4

3 に答える 3

10

EINTRLinuxは、ファイルへの書き込み/ファイルからの読み取りを回避する傾向があります。ここでの議論を参照してください。プロセスがディスク書き込みをブロックしている間、そのプロセスは中断できないスリープ状態(プロセスコード)に置かれる可能性がありますD。これは、その時点でプロセスを中断できないことを示します。これはデバイスドライバーによって異なります。Linux Device Drivers、3rd Editionのオンラインコピーは、これがカーネル側からどのように見えるかについての良いリファレンスです。

同じように動作しない可能性のある他のプラットフォーム、またはEINTRが確実に発生する可能性のあるパイプやソケットについては、引き続きEINTRを処理する必要があります。

sizeof(void *)一度に書き込むのはバイトのみであることに注意してください。

char* buf = malloc(1024*1024*128);

    if (write(fd, buf, sizeof(buf)) != sizeof(buf))

これは

const size_t BUF_SIZE = 1024*1024*128;
char* buf = malloc(BUF_SIZE);

    if (write(fd, buf, BUF_SIZE) != BUF_SIZE)
于 2012-08-07T10:58:31.573 に答える
5

2つの可能性があります:

  • 演算子を誤用しているsizeofため、書き込みはごくわずかです。したがって、writeこれは瞬時に発生し、中断されることはありません。一度に書き込むのは4バイトまたは8バイトだけです。

  • どういうわけか、あなたがに適用SA_RESTARTしたかのように、syscallが再起動されますsigaction


あなたのコードでbufは、はポインタsizeof(buf)なので、(はるかに大きい)割り当てられたスペースではなく、マシン上のポインタのサイズを生成します

于 2012-08-07T10:57:31.923 に答える
1

マニュアルページを確認するとEINTR

データが書き込まれる前に、信号によって通話が中断されました

また、signal(7)のマニュアルページから:

「遅い」デバイスでのread(2)、readv(2)、write(2)、writev(2)、およびioctl(2)呼び出し。「遅い」デバイスとは、I / O呼び出しが無期限にブロックされる可能性があるデバイスのことです。たとえば、端末、パイプ、ソケットなどです。(この定義によれば、ディスクは低速デバイスではありません。)低速デバイスでのI / O呼び出しが、シグナルハンドラーによって中断されるまでにすでにデータを転送している場合、呼び出しは成功ステータスを返します(通常は、転送されたバイト数)。

これら2つをまとめて、ディスク上のファイルに書き込み、write書き込みを開始した場合(1バイトしか書き込まれていなくても)、そのwrite呼び出しからの戻りは成功します。

于 2012-08-07T10:57:01.863 に答える