Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1778498
  • 博文数量: 438
  • 博客积分: 9799
  • 博客等级: 中将
  • 技术积分: 6092
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-25 17:25
文章分类

全部博文(438)

文章存档

2019年(1)

2013年(8)

2012年(429)

分类: 系统运维

2012-03-29 12:14:42

ISO C标准定义了两个由标准I/O库提供的函数,用来协助创建临时文件。 


  1. #include <stdio.h>

  2. char *tmpnam(char *ptr);

  3. 返回指向唯一的路径名的指针。

  4. FILE *tmpfile(void);

  5. 成功返回文件指针,失败返回NULL。

tmpname函数返回一个不与任何已有文件相同的合法路径名的字符串。这个函数每次调用会产生一个不同的路径名,最多TMP_MAX次。TMP_MAX定义在里。


尽管ISO C定义了TMP_MAX,但是C标准只要求它的值最少为25。然而SUS要求XSI系统支持一个最少10000的值。尽管这个最小值允许一个实现使用四位数(0000~9999),但多数UNIX系统的实现使用小写或大写的字符。


如果ptr为NULL,那么产生的pathname存储在一个静态 区域里,而这个区域的指针被作为这个函数的返回值。随后的tmpnam调用可以覆盖这个区域。(这意味着如果我们不只一次调用这个函数而又想保存这个路径 名,我们必须存储这个路径名的拷贝,而这是指针的拷贝。)如果ptr不为NULL,它被假设为一个指向至少L_tmpnam字符的数组的指针。(常量 L_tmpnam定义在里)。生成的路径名被存储在这个数组里,而ptr也作为这个函数的返回值。


tmpfile创建一个临时二进制文件(wb+类型),当它被关闭时或程序终止时,这个文件会被自动删除。在UNIX系统,这个文件作为二进制文件并没有什么不同。


看下面的例子:



  1. #include <stdio.h>
  2. #define MAXLINE 4096

  3. int
  4. main(void)
  5. {
  6.     char name[L_tmpnam], line[MAXLINE];
  7.     FILE *fp;

  8.     printf("%s\n", tmpnam(NULL)); /* first temp name */

  9.     tmpnam(name); /* second temp name */
  10.     printf("%s\n", name);

  11.     if ((fp = tmpfile()) == NULL) /* create temp file */
  12.         exit(1);
  13.     fputs("one line of output\n", fp); /* write to temp file */
  14.     rewind(fp);
  15.     if (fgets(line, sizeof(line), fp) == NULL)
  16.         exit(1);
  17.     fputs(line, stdout); /* print the lien we wrote */

  18.     exit(0);
  19. }

/tmp/fileV8XZkg
/tmp/filelq0E40
one line of output

tmpfile函数经常使用的标准技术是调用tmpnam创建一个唯一的路径名,然后创建这个文件,之后立即unlink它。回想下4.15节,解链接一个文件在文件关闭前都不会删除它的内容。这种方法,进程显式关闭文件或进程终止时,文件的内容会被删除。


SUS定义了两个额外的函数,作为XSI扩展,来处理临时文件。第一个是tempnam函数。



  1. #include <stdio.h>

  2. char *tmpnam(const char *directory, const char *prefix);

  3. 返回指向唯一路径名的指针。


tempnam函数是tmpnam的一个变体,允许调用者指定目录和生成路径名的前缀。directory有四种可能的选择,第一个满足的情况将作为这个目录:


1、如果环境变量TMPDIR定义了,它被作为这个目录。(我们将在7.9节描述环境变量。)


2、如果directory不为NULL,它被作为目录。


3、里的字符串P_tmpdir被作为这个目录。


4、一个本地目录,通常是/tmp,被作为这个目录。


如果prefix参数不为NULL,它应该是一个最多5字节的字符串,作为文件名的开头。


这个函数调用malloc函数来为生成的路径名开辟一个动态空间。我们可以在使用完这个路径名后释放这个空间。(我们将在7.8节讨论malloc和free函数。)


看下面的例子:



  1. #include <stdio.h>

  2. int
  3. main(int argc, char *argv[])
  4. {
  5.     if (argc != 3)
  6.         exit(1); /* usage: a.out <directory> <prefix> */

  7.     printf("%s\n", tempnam(argv[1][0] != ' ' ? argv[1] : NULL,
  8.         argv[2][0] != ' ' ? argv[2] : NULL));

  9.     exit(0);
  10. }



$ ./a.out " " pre-
/tmp/pre-QeucSV
$ ./a.out ~ pre-
/home/tommy/pre-XDvhdK
$ ./a.out ~ " "
/home/tommy/fileh5eC4M
$ TMPDIR=/var/tmp ./a.out ~ " "
/var/tmp/file3ql3ps
$ TMPDIR=/no/such/dir ./a.out ~ " "
/home/tommy/file0uZmGD

正如我们之前列出的四个步骤,目录名按照顺序尝试,而函数也检查对应的目录名是否有效。如果文件名不存在(比如/no/such/dir),这种情况会被 忽略,而下个目录名的尝试会被尝试。从这个例子,我们可以看到在这个实现上,P_tmpdir目录是/tmp。我们用来设置环境变量技术(在程序名前指定 TMPDIR=),被Bourne shell、Korn shell和bash使用。

XSI定义的第二个函数是mkstemp。它也tmpfile相似,但返回这个临时文件打开后的文件描述符,而不是文件指针。



  1. #include <stdlib.h>

  2. int mkstemp(char *template);

  3. 成功返回文件描述符,失败返回-1。


返回的文件描述符能用来写和读。这个临时文件的名字通过template字符串来选择。这个字符串是最后6个字符被设置为XXXXXX的一个路径名。如果mkstemp返回成功,它会把template字符串修改成反映这个临时文件的名字。


和tmpfile不同,这个由mkstemp创建的临时文件不会自动删除。如果我们想从系统名字空间里删除它,我们需要自己解链接它。


使用tmpnam和tempnam有一个缺陷:在唯一路径名返回和程序用这个名字创建文件之间有一个间隙。在这个时间间隙里,另一个进程可以用同样的名字创建一个文件。应该使用tmpfile和mkstemp函数,因为它们没有这个问题。


mktemp函数和mkstemp相似,除了它只创建一个适用于一个临时文件的名字。mktemp函数不创建一个文件,所以它和tmpnam和 tempnam有相同的问题。mktemp函数在SUS里被标记为一个遗留的接口。遗留接口在将来的SUS版本里可能会被删除,所以应该避免使用。

阅读(1147) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~