除非打印到stdout的内容,否则SIGXFSZ是由内核发送的?

时间:2014-07-03 06:36:24

标签: c linux

我正在学习" Unix环境下的高级编程 ",并且运动有问题 no.11 第10章

在我的计划中,我将RLIMIT_FSIZE设置为1024

因此,当写入尝试超过该限制时,内核应该将SIGXFSZ发送到我的程序。

但我发现除非SIGXFSZ打印了某些内容,否则stdout不会发送。

这是我的代码:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <signal.h>

#define BUFFSIZE 100

void xfsz_handler(int signo)
{
    fprintf(stderr, "%d, %s\n", signo, strsignal(signo));
}

int main(int argc, char* argv[])
{
    int n;
    char buf[BUFFSIZE];
    struct rlimit fsizeLimit;

    fsizeLimit.rlim_cur=1024;
    fsizeLimit.rlim_max=1024;
    if(setrlimit(RLIMIT_FSIZE, &fsizeLimit) < 0)
    {
        perror("setrlimit error");
        exit(-1);
    }

    if(signal(SIGXFSZ, xfsz_handler)==SIG_ERR)
    {
        fprintf(stderr, "set signal handler error for %d\n", SIGXFSZ);
        exit(-1);
    }

    printf("what ever\n"); /* we need this to get SIGXFSZ sent */


    while ( (n=read(STDIN_FILENO, buf, BUFFSIZE)) > 0)
    {
        int byteWrite = 0;
        if ( (byteWrite = write(STDOUT_FILENO, buf, n)) < 0)
        {
            perror("write error");
            exit(-1);
        }

        if(byteWrite!=n)
        {
            fprintf(stderr, "byteWrite=%d, n=%d\n", byteWrite, n);
            exit(-1);
        }
    }

    if (n<0)
    {
        perror("read error");
        exit(-1);
    }
    return 0;
}

如果我在代码中注释掉以下行,内核将不会传输SIGXFSZ

printf("What ever . . . \n");

为什么会这样?提前谢谢。

[root@luaDevelopment ex11]# ./myCopy < /root/workspace/AdvanceProgrammingInTheUnixEnvironment.20140627.tar.bz2 >aa.tar.bz2
byteWrite=24, n=100
[root@luaDevelopment ex11]# make
gcc -o myCopy myCopy.c -std=gnu99 -I../../lib/ -L../../lib/ -lch10
[root@luaDevelopment ex11]# ./myCopy < /root/workspace/AdvanceProgrammingInTheUnixEnvironment.20140627.tar.bz2 >aa.tar.bz2
byteWrite=24, n=100
25, File size limit exceeded
[root@luaDevelopment ex11]#

1 个答案:

答案 0 :(得分:2)

user3693690在本书的附录C中找到了答案:

  

10.11在Linux 3.2.0,Mac OS X 10.6.8和Solaris 10下,从不调用SIGXFSZ的信号处理程序[因为循环在短写时退出程序],但write返回24的计数为文件的大小达到1,024字节。当文件的大小在FreeBSD 8.0下达到1,000字节时,在下次尝试写入100字节时调用信号处理程序,并且写入调用返回-1,并将errno设置为EFBIG(“文件太大”)。在所有四个平台上,如果我们尝试在当前文件偏移量(文件末尾)进行额外写入,我们将收到SIGXFSZ并且写入将失败,返回-1并将errno设置为EFBIG。

如果这是Linux内核用来处理SIGXFSZ的方式,那就这样吧,但我觉得这很奇怪。