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);
 }