Return fprintf 的值
Return value of fprintf
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main(void)
{
FILE *fh = fopen ("file.txt", "w");
if (fh != NULL) {
int i = 0;
while(i < 5){
if (fprintf (fh, "%s", "hello") < 0)
{
fprintf (stderr, "err=%d: %s\n", errno, strerror (errno));
}
if(ferror(fh))
{
printf("wrong\n");
}
sleep(10);
}
}
return(0);
}
当我在程序 运行 期间删除文件 "file.txt" 时,我希望 fprintf 以 return 小于 0 的值来打印错误消息。但总是 fprintf returns "hello" 字符串的大小是 5.
注意:由于有10秒的sleep call,我在程序结束前删除了文件。
如果 fprintf/fwrite 写入不再存在的文件(由文件描述符指向),请说明如何生成错误消息。
在类 UNIX 系统上,"deleting" 文件不会物理删除磁盘上的文件。它只是将其 link 计数减 1。直到最后一个 link 消失,文件才真正被删除。这就是 rm
命令调用的系统调用称为 unlink
的原因。 man 2 unlink
获取更多信息。
如果您对文件创建硬 link,就会看到这样做的一个结果:
echo "hello" > file0
ln file0 file1
rm file0
rm file0
命令意味着该文件不再以该名称可见,但通过其其他名称仍然可见 file1
。如果您然后 rm file1
,实际文件最终将消失。
另一种防止文件被删除的方法是让进程打开它。您的程序创建一个文件,并创建一个名为 "file.txt"
的目录条目。当您在程序外键入 rm file.txt
时,您删除的是目录条目,而不是文件。您的程序仍然可以写入文件。它甚至可以回到文件的开头并再次读取它。
如果您的程序调用 fclose(fh)
,或者如果它终止(隐式关闭所有打开的文件),那么对磁盘文件的最后引用将消失,磁盘上的实际文件将被删除。
非 UNIX 系统(如 Windows)的行为可能不同。
还有另一种方法可以在不从磁盘读取的情况下检查目录是否被删除。
inotify 系统调用执行监视目录的工作,如果目录被删除,回调将发送到创建 inotify 实例的主程序。
一个简单的例子 - 这是从 inotify 的手册页中复制的。 link
+/* demo_inotify.c
+
+ Demonstrate the use of the inotify API.
+
+ Usage: demo_inotify pathname...
+
+ The program monitors each of the files specified on the command line for all
+ possible file events.
+
+ This program is Linux-specific. The inotify API is available in Linux 2.6.13
+ and later.
+*/
#include <sys/inotify.h>
#include <limits.h>
#include "tlpi_hdr.h"
static void /* Display information from inotify_event structure */
displayInotifyEvent(struct inotify_event *i)
{
printf(" wd =%2d; ", i->wd);
if (i->cookie > 0)
printf("cookie =%4d; ", i->cookie);
printf("mask = ");
if (i->mask & IN_ACCESS) printf("IN_ACCESS ");
if (i->mask & IN_ATTRIB) printf("IN_ATTRIB ");
if (i->mask & IN_CLOSE_NOWRITE) printf("IN_CLOSE_NOWRITE ");
if (i->mask & IN_CLOSE_WRITE) printf("IN_CLOSE_WRITE ");
if (i->mask & IN_CREATE) printf("IN_CREATE ");
if (i->mask & IN_DELETE) printf("IN_DELETE ");
if (i->mask & IN_DELETE_SELF) printf("IN_DELETE_SELF ");
if (i->mask & IN_IGNORED) printf("IN_IGNORED ");
if (i->mask & IN_ISDIR) printf("IN_ISDIR ");
if (i->mask & IN_MODIFY) printf("IN_MODIFY ");
if (i->mask & IN_MOVE_SELF) printf("IN_MOVE_SELF ");
if (i->mask & IN_MOVED_FROM) printf("IN_MOVED_FROM ");
if (i->mask & IN_MOVED_TO) printf("IN_MOVED_TO ");
if (i->mask & IN_OPEN) printf("IN_OPEN ");
if (i->mask & IN_Q_OVERFLOW) printf("IN_Q_OVERFLOW ");
if (i->mask & IN_UNMOUNT) printf("IN_UNMOUNT ");
printf("\n");
if (i->len > 0)
printf(" name = %s\n", i->name);
}
#define BUF_LEN (10 * (sizeof(struct inotify_event) + NAME_MAX + 1))
int
main(int argc, char *argv[])
{
int inotifyFd, wd, j;
char buf[BUF_LEN] __attribute__ ((aligned(8)));
ssize_t numRead;
char *p;
struct inotify_event *event;
if (argc < 2 || strcmp(argv[1], "--help") == 0)
usageErr("%s pathname...\n", argv[0]);
inotifyFd = inotify_init(); /* Create inotify instance */
if (inotifyFd == -1)
errExit("inotify_init");
+ /* For each command-line argument, add a watch for all events */
+
for (j = 1; j < argc; j++) {
wd = inotify_add_watch(inotifyFd, argv[j], IN_ALL_EVENTS);
if (wd == -1)
errExit("inotify_add_watch");
printf("Watching %s using wd %d\n", argv[j], wd);
}
for (;;) { /* Read events forever */
numRead = read(inotifyFd, buf, BUF_LEN);
if (numRead == 0)
fatal("read() from inotify fd returned 0!");
if (numRead == -1)
errExit("read");
printf("Read %ld bytes from inotify fd\n", (long) numRead);
/* Process all of the events in buffer returned by read() */
for (p = buf; p < buf + numRead; ) {
event = (struct inotify_event *) p;
displayInotifyEvent(event);
p += sizeof(struct inotify_event) + event->len;
}
}
exit(EXIT_SUCCESS);
}
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main(void)
{
FILE *fh = fopen ("file.txt", "w");
if (fh != NULL) {
int i = 0;
while(i < 5){
if (fprintf (fh, "%s", "hello") < 0)
{
fprintf (stderr, "err=%d: %s\n", errno, strerror (errno));
}
if(ferror(fh))
{
printf("wrong\n");
}
sleep(10);
}
}
return(0);
}
当我在程序 运行 期间删除文件 "file.txt" 时,我希望 fprintf 以 return 小于 0 的值来打印错误消息。但总是 fprintf returns "hello" 字符串的大小是 5.
注意:由于有10秒的sleep call,我在程序结束前删除了文件。
如果 fprintf/fwrite 写入不再存在的文件(由文件描述符指向),请说明如何生成错误消息。
在类 UNIX 系统上,"deleting" 文件不会物理删除磁盘上的文件。它只是将其 link 计数减 1。直到最后一个 link 消失,文件才真正被删除。这就是 rm
命令调用的系统调用称为 unlink
的原因。 man 2 unlink
获取更多信息。
如果您对文件创建硬 link,就会看到这样做的一个结果:
echo "hello" > file0
ln file0 file1
rm file0
rm file0
命令意味着该文件不再以该名称可见,但通过其其他名称仍然可见 file1
。如果您然后 rm file1
,实际文件最终将消失。
另一种防止文件被删除的方法是让进程打开它。您的程序创建一个文件,并创建一个名为 "file.txt"
的目录条目。当您在程序外键入 rm file.txt
时,您删除的是目录条目,而不是文件。您的程序仍然可以写入文件。它甚至可以回到文件的开头并再次读取它。
如果您的程序调用 fclose(fh)
,或者如果它终止(隐式关闭所有打开的文件),那么对磁盘文件的最后引用将消失,磁盘上的实际文件将被删除。
非 UNIX 系统(如 Windows)的行为可能不同。
还有另一种方法可以在不从磁盘读取的情况下检查目录是否被删除。
inotify 系统调用执行监视目录的工作,如果目录被删除,回调将发送到创建 inotify 实例的主程序。
一个简单的例子 - 这是从 inotify 的手册页中复制的。 link
+/* demo_inotify.c
+
+ Demonstrate the use of the inotify API.
+
+ Usage: demo_inotify pathname...
+
+ The program monitors each of the files specified on the command line for all
+ possible file events.
+
+ This program is Linux-specific. The inotify API is available in Linux 2.6.13
+ and later.
+*/
#include <sys/inotify.h>
#include <limits.h>
#include "tlpi_hdr.h"
static void /* Display information from inotify_event structure */
displayInotifyEvent(struct inotify_event *i)
{
printf(" wd =%2d; ", i->wd);
if (i->cookie > 0)
printf("cookie =%4d; ", i->cookie);
printf("mask = ");
if (i->mask & IN_ACCESS) printf("IN_ACCESS ");
if (i->mask & IN_ATTRIB) printf("IN_ATTRIB ");
if (i->mask & IN_CLOSE_NOWRITE) printf("IN_CLOSE_NOWRITE ");
if (i->mask & IN_CLOSE_WRITE) printf("IN_CLOSE_WRITE ");
if (i->mask & IN_CREATE) printf("IN_CREATE ");
if (i->mask & IN_DELETE) printf("IN_DELETE ");
if (i->mask & IN_DELETE_SELF) printf("IN_DELETE_SELF ");
if (i->mask & IN_IGNORED) printf("IN_IGNORED ");
if (i->mask & IN_ISDIR) printf("IN_ISDIR ");
if (i->mask & IN_MODIFY) printf("IN_MODIFY ");
if (i->mask & IN_MOVE_SELF) printf("IN_MOVE_SELF ");
if (i->mask & IN_MOVED_FROM) printf("IN_MOVED_FROM ");
if (i->mask & IN_MOVED_TO) printf("IN_MOVED_TO ");
if (i->mask & IN_OPEN) printf("IN_OPEN ");
if (i->mask & IN_Q_OVERFLOW) printf("IN_Q_OVERFLOW ");
if (i->mask & IN_UNMOUNT) printf("IN_UNMOUNT ");
printf("\n");
if (i->len > 0)
printf(" name = %s\n", i->name);
}
#define BUF_LEN (10 * (sizeof(struct inotify_event) + NAME_MAX + 1))
int
main(int argc, char *argv[])
{
int inotifyFd, wd, j;
char buf[BUF_LEN] __attribute__ ((aligned(8)));
ssize_t numRead;
char *p;
struct inotify_event *event;
if (argc < 2 || strcmp(argv[1], "--help") == 0)
usageErr("%s pathname...\n", argv[0]);
inotifyFd = inotify_init(); /* Create inotify instance */
if (inotifyFd == -1)
errExit("inotify_init");
+ /* For each command-line argument, add a watch for all events */
+
for (j = 1; j < argc; j++) {
wd = inotify_add_watch(inotifyFd, argv[j], IN_ALL_EVENTS);
if (wd == -1)
errExit("inotify_add_watch");
printf("Watching %s using wd %d\n", argv[j], wd);
}
for (;;) { /* Read events forever */
numRead = read(inotifyFd, buf, BUF_LEN);
if (numRead == 0)
fatal("read() from inotify fd returned 0!");
if (numRead == -1)
errExit("read");
printf("Read %ld bytes from inotify fd\n", (long) numRead);
/* Process all of the events in buffer returned by read() */
for (p = buf; p < buf + numRead; ) {
event = (struct inotify_event *) p;
displayInotifyEvent(event);
p += sizeof(struct inotify_event) + event->len;
}
}
exit(EXIT_SUCCESS);
}