我正在学习" 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]#
答案 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的方式,那就这样吧,但我觉得这很奇怪。