2012-11-26 12:17:20 xiaolong2w 阅读数 5994

在linux下很大一部分人创建文件的时候很少用creat了,大部分都用open来代替,其实这样是完全可以的因为creat函数就等价于下面的open函数:

open(const char * pathname, (O_CREAT|O_TRUNC|O_WRONLY));

其实要是仔细看这个open函数也就能发现,为啥用creat创建的文件,在进行读操作会出现errno:9 Bad file descriptor的错误。

一开始我就单纯的以为那个O_WRONLY可以随便的换成O_RDONLY或者O_RDWR呢,但是其实不是那样的,

creat函数的返回值就是如果成功返回一个只写的文件描述符,主意“只写”的,失败返回-1;

也就是说,对这个文件做读操作的就会出错,如下例:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

extern int errno;

void my_err(char * str_string, int line)//自己定义的出错处理函数
{
        fprintf(stderr, "line:%d...errno:%d", line, errno);
        perror(str_string);
        exit(1);
}

int main(void)
{
        int fd, ret;
        char read_buf[64];
        char write_buf[32] = "Hello World!";
        if((fd = creat("text.c",S_IRWXU)) == -1)//创建text.c文件
        {
                my_err("creat", __LINE__);
        }
        if(write(fd, write_buf, strlen(write_buf)) < 0)
        {
                my_err("write", __LINE__);
        }
        if((ret = read(fd, read_buf,32)) < 0){
                my_err("read", __LINE__);
        }
        for(int i = 0; i < ret; i++)
                printf("%c", read_buf[i]);
        printf("\n");
        return 0;
}

gcc -o creat creat.c -std=c99 -Wall

./creat会出现如下错误

line:33...errno:9read: Bad file descriptor

所以大家要注意,creat函数返回的文件描述符,只可做写操作,不可做读操作,如果要进行读操作,可用open重新打开,或者创建的时候直接用open函数就可以了。

2013-07-28 13:17:14 sonbai 阅读数 2445

creat函数完全可以被open函数替代:
open(pathname, O_WRONLY | O_CREAT | O_TRUNC, mode);

[lingyun@localhost create]$ vim creat.c

 + creat.c                                                                                                     
/*********************************************************************************
 *      Copyright:  (C) 2013 fulinux<fulinux@sina.com> 
 *                  All rights reserved.
 *
 *       Filename:  creat.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(07/28/2013~)
 *         Author:  fulinux <fulinux@sina.com>
 *      ChangeLog:  1, Release initial version on "07/28/2013 01:05:30 PM"
 *                 
 ********************************************************************************/


#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


#define PERM 0755


int main(void)
{
    static char filename[] = "file.txt";
    int fd;


    fd = creat(filename,PERM);


    if(fd < 0)
        printf("[%s] create fail !!!\n",filename);
    else
        printf("[%s] open success !\n",filename);
    exit(0);
}
~                                                                                                               
~                                                                                                               
~                                                                                                               
~                                                                                                               
~                                                                                                               
~                                                                                                               
~                                                                                                               
~                                                                                                               
~                                                                                                               
~                                                                                                               
~                                                                                                               
~                                                                                                               
~                                                                                                               
~                                                                                                               
~                                                                                                               
 ~/apue/creat/creat.c[+]   CWD: /usr/local/src/lingyun/apue/creat   Line: 17/33:18                           
"create.c" 33L, 869C written


[lingyun@localhost creat]$ gcc creat.c 
[lingyun@localhost creat]$ ./a.out 
[file.txt] open success !
[lingyun@localhost creat]$ ls
a.out  creat.c  file.txt



2011-09-07 22:37:39 songyang516 阅读数 19873
 open 函数用于打开和创建文件。以下是 open 函数的简单描述

        #include <fcntl.h>

        int open(const char *path, int access,int mode)

                    返回值:成功则返回文件描述符,否则返回 -1

  path 要打开的文件路径和名称  

如 C:/cpp/a.cpp                     

 

 access 用于指定文件的打开/创建模式,宏定义和含义如下:                       
        O_RDONLY         1    只读打开                        
        O_WRONLY         2    只写打开                        
        O_RDWR           4    读写打开

 

还可选择以下模式与以上3种基本模式相与:                    
   O_CREAT     0x0100   创建一个文件并打开                
   O_TRUNC     0x0200   打开一个已存在的文件并将文件长度设置为0,其他属性保持         
   O_EXCL      0x0400   未使用                            
   O_APPEND    0x0800   追加打开文件                     
   O_TEXT      0x4000   打开文本文件翻译CR-LF控制字符     
   O_BINARY    0x8000   打开二进制字符,不作CR-LF翻译 

 

mode 该参数仅在access=O_CREAT(创建一个文件并打开 )方式下使用,其取值如下:     
        S_IFMT      0xF000   文件类型掩码                     
        S_IFDIR     0x4000   目录                             
        S_IFIFO     0x1000   FIFO 专用                        
        S_IFCHR     0x2000   字符专用                         
        S_IFBLK     0x3000   块专用                           
        S_IFREG     0x8000   只为0x0000                       
        S_IREAD     0x0100   可读                             
        S_IWRITE    0x0080   可写                             
        S_IEXEC     0x0040   可执行   

 

   create函数也能打开一个文件,如果文件不存在,则创建它。和open一样,creat也在调用成功后返回一个文件描述符,如果失败,则设置errno变量并返回-1.

creat的原型为:

int creat (const char *pathname,mode_t mode);

他等价于:

open(pathname,O_CREAT | O_TRUNC | O_WRONLY,mode);

在使用完某个函数后要关闭他,使用  close函数。close只有一个参数,即open返回的文件描述符.

close的原型为:

              #include <unist.d>

               int close(int fd);    

2012-11-15 19:45:04 qianguozheng 阅读数 5265

Linux中系统调用很多,但是再多也有几种不变的根本:创建,打开,写,读,关闭,删除,等最最基本的操作,就像人们所常说的,Linux上的一切我们都可以当做文件来处理,既然是文件,那么以上的几种操作就是必须的,还有一些高级的,我会陆续介绍。

想到这个函数,就想到了我们的open还不具备创建文件的能力之前,那时的creat是多么的辉煌,现在的open就像腾讯那样的霸道,什么都做,简直是百科全书。废话不多说了,介绍下creat()


位于#include <fcntl.h>

int creat(const char *pathname, mode_t mode);

成功返回为只写打开的文件描述符,若出错则返回-1.

注意:此函数等效于:

 open(pathname, O_WRONLY | O_CREAT | O_TRUNC, mode);

下面给个例子

很奇怪我没有包含 fcntl.h头文件,程序并没有报错,希望了解内情的同志留个言,让俺也长下见识。

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

int main(void)
{
	int fd = -1;
	
	fd = creat("tmp.lock",00644);
	if (0 > fd)
	{
		printf("errno:%s\n",strerror(errno));
	}
	else
	{
		close(fd);
	}
	printf("Execute ok: %d\n", fd); // 关闭之后再打印,fd的值竟然不变(测试才知道的)。
	return 0;
} 


写这个函数的目的为别的,就是想测测 creat创建的文件已经创建后,再次调用是否会出现 EEXIST错误,结果很失望,不会。

同一个程序执行数次,所得到的结果没有变化,fd=3。

不过学了样东西,慢慢来吧,啥都得从头开始,是不。

open就不行了。

需要fcntl.h------{小弟真的很困惑,难道标准库中包含了creat,为什么 open就需要引用这个头文件?}

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>

int main(void)
{
	int fd = -1;

	fd = open("tmp.lock", O_WRONLY | O_CREAT | O_TRUNC, 00644);
	printf("fd:%d\n",fd);
	if(0 > fd)
	{
		printf("errno:%s\n",strerror(errno));
	}
	else
	{
		close(fd);
	}
	printf("Execute ok");
	return 0;
}
执行结果同上。


下面我就用了下 O_EXCL flag

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>

int main(void)
{
	int fd = -1;

	fd = open("tmp.lock", O_WRONLY | O_CREAT | O_EXCL, 00644);
	printf("fd:%d\n",fd);
	if(0 > fd)
	{
		printf("errno:%s\n",strerror(errno));
	}
	else
	{
		close(fd);
	}
	printf("Execute ok");
	return 0;
} 

这次返回了EEXIST, fd = -1, 这下正合我意了。


关于open的一些列的flag,常用的也就那几个,列出来给大家个参考吧:

http://os.51cto.com/art/201108/286554.htm

描述 (DESCRIPTION)
open() 通常 用于 将 路径名 转换为 一个 文件描述符 (一个 非负的 小 整数, 在 read , write 等 I/O操作中 将会被使用). 当 open() 调用 成功, 它会 返回 一个 新的 文件描述符 (永远取 未用 描述符的 最小值). 这个调用 创建 一个 新的 打开文件, 即 分配 一个 新的 独一无二的 文件描述符, 不会与 运行中的 任何 其他程序 共享 (但 可以 通过 fork (2) 系统调用 实现 共享). 这个 新的 文件描述符 在其后 对 打开文件操作 的函数 中 使用.(参考fcntl(2)). 文件的 读写 指针 被 置于 文件头


参数 flags 是通过 O_RDONLY, O_WRONLY 或 O_RDWR (指明 文件 是以 只读 , 只写 或 读写 方式 打开的) 与 下面的 零个 或 多个 可选模式 按位 -or 操作 得到的:


O_CREAT
若文件 不存在 将 创建 一个 新 文件. 新 文件 的 属主 (用户ID) 被 设置 为 此 程序 的 有效 用户 的 ID. 同样 文件 所属 分组 也 被 设置 为 此 程序 的 有效 分组 的 ID 或者 上层 目录 的 分组 ID (这 依赖 文件系统 类型 ,装载选项 和 上层目录 的 模式, 参考,在mount(8) 中 描述 的 ext2 文件系统 的 装载选项 bsdgroups 和 sysvgroups )
O_EXCL
通过 O_CREAT, 生成 文件 , 若 文件 已经 存在 , 则 open 出错 , 调用 失败 . 若是 存在 符号联接 , 将会 把 它的 联接指针 的 指向 文件 忽略. O_EXCL is broken on NFS file systems, programs which rely on it for performing locking tasks will contain a race condition. The solution for performing atomic file locking using a lockfile is to create a unique file on the same fs (e.g., incorporating hostname and pid), uselink(2) to make a link to the lockfile. If link() returns 0, the lock is successful. Otherwise, use stat(2) on the unique file to check if its link count has increased to 2, in which case the lock is also successful.
O_NOCTTY
假如 pathname 引用 一个 终端设备 --- 参考 tty(4) --- 即使 进程 没有 控制终端 ,这个 终端 也 不会 变成 进程 的 控制 终端.
O_TRUNC
假如 文件 已经 存在 , 且是 一个 普通 文件 ,打开 模式 又是 可写(即 文件 是 用 O_RDWR 或 O_WRONLY 模式 打开 的) , 就把 文件 的 长度 设置 为 零 , 丢弃 其中的 现有 内容.若 文件 是 一个 FIFO 或 终端设备 文件 , O_TRUNC 标志 被 忽略. 其他 O_TRUNC 的 作用 是 不 具体 指定 的 (在 许多 Linux 版本 中 , 通常 会 被 忽略 , 其他 的 一些 版本 将 返回 一个 错误)
O_APPEND
文件 以 追加 模式 打开 . 在 写 以前 , 文件 读写 指针 被 置 在 文件 的 末尾 . as if with lseek. O_APPEND may lead to corrupted files on NFS file systems if more than one process appends data to a file at once. This is because NFS does not support appending to a file, so the client kernel has to simulate it, which can't be done without a race condition.
O_NONBLOCK 或 O_NDELAY
打开(open) 文件 可以 以 非块(non-blocking) 模式 打开 . 此时 文件 并 没有 打开 , 也 不能 使用 返回 的文件描述符 进行 后续 操作 , 而是 使 调用 程序 等待 . 此 模式 是 为了 FIFO (命名管道) 的 处理 , 参考 fifo(4). 这种 模式 对 除了 FIFO 外 没有 任何 影响 .
O_SYNC
打开 文件 实现 I/O 的 同步 . 任何 通过 文件描述符 对 文件 的 write 都会 使 调用 的 进程 中断 , 直到 数据 被 真正 写入 硬件 中 . 其他 , 参考 RESTRICTIONS.
O_NOFOLLOW
假如 pathname 是 一个 符号 联接 , 则 打开 失败 . 这是 FreeBSD 的 扩充 , 从 2.1.126 版本 以来 被 引入 到 Linux 中来 . 从 glibc2.0.100 库 以来 , 头文件 中 包括 了 这个 参数 的 定义; 
  kernel 2.1.126 以前 将 忽略 它的 使用.
O_DIRECTORY
假如 pathname 不是 目录 , 打开 就 失败 . 这个 参数 是 Linux 特有 的 , 在 kernel 2.1.126 中 加入 , 为了 避免 在 调用 FIFO 或 磁带设备 时 的 denial-of-service 问题 , 但是 不应该 在 执行 opendir 以外 使用.
O_LARGEFILE
在 32位 系统 中 支持 大 文件系统 , 允许 打开 那些 用 31位 都 不能 表示 其 长度 的 大 文件 .
在 文件 打开 后 , 这些 可选 参数 可以 通过 fcntl 来 改变 .


在 新文件 被 创建 时 , 参数 mode 具体 指明 了 使用 权限 . 他 通常 也 会 被 umask修改 . 所以 一般 新建 文件 的 权限 为 (mode & ~umask). 注意 模式 只 被 应用 于 将来 对 这 新文件 的 使用 中; open 调用 创建 一个 新的 只读 文件 , 但 仍 将 返回 一个 可 读写 文件 描述符.


后面 是 一些 mode 的 具体 参数:


S_IRWXU
00700 允许 文件 的 属主 读 , 写 和 执行 文件
S_IRUSR (S_IREAD)
00400 允许 文件 的 属主 读 文件
S_IWUSR (S_IWRITE)
00200 允许 文件 的 属主 写 文件
S_IXUSR (S_IEXEC)
00100 允许 文件 的 属主 执行 文件
S_IRWXG
00070 允许 文件 所在 的 分组 读 , 写 和 执行 文件
S_IRGRP
00040 允许 文件 所在 的 分组 读 文件
S_IWGRP
00020 允许 文件 所在 的 分组 写 文件
S_IXGRP
00010 允许 文件 所在 的 分组 执行 文件
S_IRWXO
00007 允许 其他 用户 读 , 写 和 执行 文件
S_IROTH
00004 允许 其他 用户 读 文件
S_IWOTH
00002 允许 其他 用户 写 文件
S_IXOTH
00001 允许 其他 用户 执行 文件
mode 只有 当 在 flags 中 使用 O_CREAT 时 才 有效 , 否则 被 忽略.


creat 相当 于 open 的 参数 flags 等于 O_CREAT|O_WRONLY|O_TRUNC.  


RETURN VALUE 返回值
open 和 creat 都 返回 一个 新的 文件描述符 (若是 有 错误 发生 返回 -1 ,并在errno 设置 错误 信息). 注意 open 可以 打开 设备 专用 文件 , 但是 creat 不能创建,需要用 mknod(2) 来代替.


On NFS file systems with UID mapping enabled, open may return a file descriptor but e.g. read(2) requests are denied with EACCES. This is because the client performs open by checking the permissions, but UID mapping is performed by the server upon read and write requests.


若 文件 是 新 建立 的 , 他 的 atime(上次访问时间), ctime(创建时间), mtime(修改时间) 都 被 修改 为 当前 时间 , 上层 目录 的atime , ctime 也 被 同样 修改 . 其他的 , 假如 文件 是 由 O_TRUNC 参数 修改的 ,它的 ctime , mtime 域 也 被 设置 为 当前 时间.


ERRORS 错误信息
EEXIST
参数 O_CREAT and O_EXCL 被使用,但是文件( pathname )已经存在.
EISDIR
文件名 ( pathname ) 是 一个 目录 , 而 又 涉及 到 写 操作.
EACCES


 访问 请求 不 允许 (权限不够) , 在 文件名 ( pathname )中 有 一 目录 不允许 搜索 (没有 执行权限) , 或者 文件 还 不存在 且 对 上层目录 的 写 操作 又 不允许.
ENAMETOOLONG
文件名 ( pathname ) 太 长 了
ENOENT
目录 ( pathname ) 不存在 或者 是 一个 悬空 的 符号 联接.
ENOTDIR
pathname 不是 一个 子目录
ENXIO
使用 O_NONBLOCK | O_WRONLY, 命名 的 文件 是 FIFO , 所读 文件 还 没有 打开 的 文件 , 或者 , 打开 一个 设备 专用 文件 而 相应 的 设备 不存在
ENODEV
文件 ( pathname ) 引用 了 一个 设备 专用 文件 , 而 相应 的 设备 又 不存在. (这是 linux kernel 的 一个bug - ENXIO 一定 会 被 返回 .)
EROFS
文件 ( pathname ) 是 一个 只读 文件 , 又有 写 操作 被 请求.
ETXTBSY
文件 ( pathname ) 是 一个 正在 被 执行 的 可 执行 文件 ,又有 写 操作 被 请求.
EFAULT
pathname 在一个你不能访问的地址空间.
ELOOP
在 分解 pathname 时 , 遇到 太多 符号联接 或者 指明 O_NOFOLLOW 但是 pathname 是 一个 符号联接
ENOSPC
pathname 将要被创建,但是设备又没有空间储存 pathname 文件了
ENOMEM
可 获得 的 核心内存(kernel memory) 不够
EMFILE
程序打开的文件数已经达到最大值了
ENFILE
系统打开的总文件数已经达到了极限


2020-03-11 15:39:41 Wangguang_ 阅读数 10

Linux系统编程 文件操作之creat

creat函数的头文件:

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

 

creat函数简介:

函数原型:

int creat(const char *pathname, mode_t mode);
  • 参数1:文件绝对路径

  • 参数2:创建文件的初始访问权限

 

返回值:

  • 返回值大于0,则创建成功,返回值为文件描述符

  • 返回值小于0,则文件创建失败

 

creat函数使用实例:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
​
int main()
{
        int fd;
        char *file = "/home/linuxsystemcode/file/2.txt";
        fd = creat(file,0777);
        if(fd < 0)
                printf("The file create failed!!!\n");
        else
                printf("%s fd is: %d\n",file,fd);
​
        return 0;
}

 

没有更多推荐了,返回首页