在 Linux 中使用临时文件进行 C 语言编程

举报
Tiamo_T 发表于 2022/06/25 14:47:34 2022/06/25
【摘要】 创建临时文件来保存数据是软件开发人员的一种流行做法。

创建临时文件来保存数据是软件开发人员的一种流行做法。存在几个用于创建临时文件的系统调用。现在有人会想,为什么我们需要系统调用来创建临时文件。这背后的主要原因是拥有唯一的临时文件名。假设有一个程序在运行时创建了一个临时文件,并假设同一程序的多个实例同时运行。如果没有记住临时文件的唯一性,那么同一程序的多个实例可能会尝试创建具有相同名称的临时文件,从而导致冲突。

有许多系统调用可用于操作临时文件:

  •  
  •  mkstemp()
  •  tmpfile()
  •  tempnam()
  •  tmpnam()
  •  unlink()

mkstemp、tmpfile、tempnam 和 tmpnam 函数用于创建临时文件,而 unlink 函数用于删除创建的临时文件。在本文中,我们将重点关注 mkstemp() 和 unlink() 系统调用。

mkstemp() 和 unlink() 系统调用

mkstemp() 的签名如下所示:

#include <stdlib.h>
int mkstemp(char *template);

该系统调用创建并打开临时文件并返回它的打开文件描述符。参数“模板”用于生成临时文件名。由于'template' 字面上的作用类似于模板名称,因此作为'template' 传递的缓冲区的最后六个字符必须包含“XXXXXX”,因为这些字符被系统调用替换以使临时文件名唯一。

unlink() 的签名如下所示:

#include <unistd.h>
int unlink(const char *pathname);

unlink() 从文件系统中删除一个名称。如果该名称是文件的最后一个链接,并且没有进程打开该文件,则该文件将被删除,并且它正在使用的空间可供重用。如果名称是文件的最后一个链接,但任何进程仍然打开该文件,则该文件将一直存在,直到最后一个引用它的文件描述符被关闭。如果名称引用了符号链接,则删除该链接。如果名称引用了套接字、fifo 或设备,则删除它的名称,但打开对象的进程可以继续使用它。

一个例子

让我们看一个示例,我们使用 mkstemp() 和 unlink() 调用来演示它们在操作临时文件方面的用法。

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<errno.h>

int main(void)
{
    // buffer to hold the temporary file name
    char nameBuff[32];
    // buffer to hold data to be written/read to/from temporary file
    char buffer[24];
    int filedes = -1,count=0;

    // memset the buffers to 0
    memset(nameBuff,0,sizeof(nameBuff));
    memset(buffer,0,sizeof(buffer));

    // Copy the relevant information in the buffers
    strncpy(nameBuff,"/tmp/myTmpFile-XXXXXX",21);
    strncpy(buffer,"Hello World",11);

    errno = 0;
    // Create the temporary file, this function will replace the 'X's
    filedes = mkstemp(nameBuff);

    // Call unlink so that whenever the file is closed or the program exits
    // the temporary file is deleted
    unlink(nameBuff);

    if(filedes<1)
    {
        printf("\n Creation of temp file failed with error [%s]\n",strerror(errno));
        return 1;
    }
    else
    {
        printf("\n Temporary file [%s] created\n", nameBuff);
    }

    errno = 0;
    // Write some data to the temporary file
    if(-1 == write(filedes,buffer,sizeof(buffer)))
    {
        printf("\n write failed with error [%s]\n",strerror(errno));
        return 1;
    }

    printf("\n Data written to temporary file is [%s]\n",buffer);

    // reset the buffer as it will be used in read operation now
    memset(buffer,0,sizeof(buffer));

    errno = 0;
    // rewind the stream pointer to the start of temporary file
    if(-1 == lseek(filedes,0,SEEK_SET))
    {
        printf("\n lseek failed with error [%s]\n",strerror(errno));
        return 1;
    }

    errno=0;
    // read the data from temporary file
    if( (count =read(filedes,buffer,11)) < 11 )
    {
        printf("\n read failed with error [%s]\n",strerror(errno));
        return 1;
    }

    // Show whatever is read
    printf("\n Data read back from temporary file is [%s]\n",buffer);

    return 0;
}

在上面的例子中:

  • 使用 mkstemp() 函数创建并打开临时文件。
  •  此函数使用一些字符更新我们使用的名称中的 X,使整体名称独一无二。
  •  在创建之后,函数 unlink() 被调用。
  •  调用 unlink() 不会立即删除文件,而是等待文件关闭或进程退出。
  •  通过 write 函数将一些数据写入临时文件
  •  通过读取功能,数据被读回。
  •  以上两个操作说明临时文件可以作为任何其他普通文件进行文件操作。
  •  一旦进程退出,文件就会被 unlink() 删除。

上述程序的输出是:

# ./tempfile 

 Temporary file [/tmp/myTmpFile-wH5sLq] created

 Data written to temporary file is [Hello World]

 Data read back from temporary file is [Hello World]

所以我们看到我们在临时文件名模板中使用的 Xs 实际上被一些随机字符(在本例中为 wH5sLq)替换,使临时文件名唯一。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。