C系统调用open/read/write/close和O_CREAT | O_EXCL

And*_*anu 6 c system-calls

给出以下代码(它应该在"helloworld"文件中编写"helloworld",然后阅读文本):

#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

#define FNAME "helloworld"

int main(){ 
    int filedes, nbytes;
    char buf[128];

    /* Creates a file */
    if((filedes=open(FNAME, O_CREAT | O_EXCL | O_WRONLY | O_APPEND, 
        S_IRUSR | S_IWUSR)) == -1){
            write(2, "Error1\n", 7);
    }

    /* Writes hello world to file */
    if(write(filedes, FNAME, 10) != 10)
        write(2, "Error2\n", 7);

    /* Close file */
    close(filedes);

    if((filedes = open(FNAME, O_RDONLY))==-1)
        write(2, "Error3\n", 7);

    /* Prints file contents on screen */    
    if((nbytes=read(filedes, buf, 128)) == -1)
        write(2, "Error4\n", 7);

    if(write(1, buf, nbytes) != nbytes)
        write(2, "Error5\n", 7);

    /* Close file after read */
    close(filedes); 

    return (0);
}
Run Code Online (Sandbox Code Playgroud)

我第一次运行程序时,输出是:

helloworld
Run Code Online (Sandbox Code Playgroud)

之后每次运行程序时,输出为:

Error1
Error2
helloworld
Run Code Online (Sandbox Code Playgroud)

我不明白为什么没有附加文本,因为我已经指定了O_APPEND文件.是因为我加入了O_CREAT吗?它已经创建了文件,不应忽略O_CREAT吗?

Jul*_*ano 12

O_EXCL强制创建文件.如果文件已存在,则调用失败.

它用于确保必须创建文件,并在第三个参数中传递给定的权限.简而言之,您有以下选择:

  • O_CREAT:如果文件尚不存在,则使用给定的权限创建文件.如果该文件存在,则会打开该文件并忽略权限.
  • O_CREAT | O_EXCL:如果文件尚不存在,则使用给定的权限创建文件.如果文件存在,则失败.这对于创建锁定文件并保证对文件的独占访问非常有用(只要使用该文件的所有程序都遵循相同的协议).
  • O_CREAT | O_TRUNC:如果文件尚不存在,则使用给定的权限创建文件.否则,将文件截断为零字节.当我们想到"创建一个新的空白文件"时,这会产生更多的效果.但是,它保留了现有文件中已存在的权限.

手册页中的更多信息:

O_EXCL

与O_CREAT一起使用时,如果文件已存在,则表示错误,open()将失败.在这种情况下,无论指向何处,都存在符号链接.O_EXCL在NFS文件系统上被破坏; 依赖它来执行锁定任务的程序将包含竞争条件.使用锁文件执行原子文件锁定的解决方案是在同一文件系统上创建一个唯一文件(例如,合并主机名和pid),使用link(2)建立到lockfile的链接.如果link()返回0,则锁定成功.否则,在唯一文件上使用stat(2)来检查其链接计数是否已增加到2,在这种情况下锁定也是成功的.