openat与open的区别及用法示例
从2.6.16版本开始,GNU/Linux引入opeant系统调用:
#define _XOPEN_SOURCE 700 /* Or define _POSIX_C_SOURCE >= 200809 */
#include <fcntl.h>
int openat(int dirfd , const char * pathname , int flags , ... /* mode_t mode */);
Returns file descriptor on success, or –1 on error
同open相比,多了一个dirfd参数。关于它的用法,参考以下解释:
If pathname specifies a relative pathname, then it is interpreted relative to the directory referred to by the open file descriptor dirfd, rather than relative to the process’s current working directory.
If pathname specifies a relative pathname, and dirfd contains the special value AT_FDCWD , then pathname is interpreted relative to the process’s current working directory (i.e., the same behavior as open(2)).
If pathname specifies an absolute pathname, then dirfd is ignored.
总结起来,如果pathname是绝对路径,则dirfd参数没用。如果pathname是相对路径,并且dirfd的值不是AT_FDCWD,则pathname的参照物是相对于dirfd指向的目录,而不是进程的当前工作目录;反之,如果dirfd的值是AT_FDCWD,pathname则是相对于进程当前工作目录的相对路径,此时等同于open。参考kernel代码则一目了然:
引入openat(及其它at结尾的函数)有以下两个原因:
First, openat() allows an application to avoid race conditions that could occur when using open(2) to open files in directories other than the current working directory. These race conditions result from the fact that some component of the directory prefix given to open(2) could be changed in parallel with the call to open(2). Such races can be avoided by opening a file descriptor for the target directory, and then specifying that file descriptor as the dirfd argument of openat().
Second, openat() allows the implementation of a per-thread “current working directory”, via file descriptor(s) maintained by the application. (This functionality can also be obtained by tricks based on the use of /proc/self/fd/dirfd, but less efficiently.)
引入openat是方便一个进程内的各线程可拥有不同的当前目录,传统的chdir会影响整个进程,而使用openat只需要每个线程在初始化时打开一个目录(调用open),然后就可以以openat在“当前目录”操作文件了,如:
int dirfd = open("/tmp"); // 相当于chdir到“/tmp”
int filefd = openat(dirfd, "myfile"); // 在/tmp目录下打开“myfile”文件
用法示例:
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h> void creat_at(char *dir_path, char *relative_path)
{
int dir_fd;
int fd;
int flags;
mode_t mode; dir_fd = open(dir_path, O_RDONLY); //fd参数是通过打开相对路径名所在的目录来获取。
if (dir_fd < )
{
perror("open");
exit(EXIT_FAILURE);
} flags = O_CREAT | O_TRUNC | O_RDWR;
mode = ; //-rw-r-----
fd = openat(dir_fd, relative_path, flags, mode);
if (fd < )
{
perror("openat");
exit(EXIT_FAILURE);
} write(fd, "HELLO", ); close(fd);
close(dir_fd);
} int main()
{
creat_at("../03.文件IO", "log.txt");
return ;
}
借用dirfd,将DIR*转换成int类型的文件描述符
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdio.h>
#include <unistd.h> int main()
{
DIR *dir;
int dirfd2;
int fd;
int n; dir = opendir("../03.文件IO");
if(NULL == dir)
{
perror("open dir error");
return -;
}
dirfd2 = dirfd(dir);
if(- == dirfd2)
{
perror("dirfd error");
return -;
} fd = openat(dirfd2,"output.log",O_CREAT|O_RDWR|O_TRUNC, \
S_IRWXU|S_IRWXG|S_IRWXO);
if(- == fd)
{
perror("opeat error");
return -;
}
n = write(fd,"Hello world!\n",); close(fd);
closedir(dir); return ; }
参考资料:
openat(2) – Linux man page
The Linux programming interface
http://blog.csdn.net/wang1902568721/article/details/47796173
http://bbs.chinaunix.net/thread-2081442-1-1.html
openat与open的区别及用法示例的更多相关文章
- Linux find 用法示例
Linux中find常见用法示例 ·find path -option [ -print ] [ -exec -ok command ] {} \; find命令的参数 ...
- GROUP BY,WHERE,HAVING之间的区别和用法
GROUP BY,WHERE,HAVING之间的区别和用法 分类: Oracle学习2009-11-01 23:40 21963人阅读 评论(6) 收藏 举报 mathmanagersql数据库m ...
- [转]Linux中find常见用法示例
Linux中find常见用法示例[转]·find path -option [ -print ] [ -exec -ok command ] {} \;find命令的参 ...
- oracle中to_date详细用法示例(oracle日期格式转换)
这篇文章主要介绍了oracle中to_date详细用法示例,包括期和字符转换函数用法.字符串和时间互转.求某天是星期几.两个日期间的天数.月份差等用法 TO_DATE格式(以时间:2007-11-02 ...
- SQL Server连接查询之Cross Apply和Outer Apply的区别及用法(转载)
先简单了解下cross apply的语法以及会产生什么样的结果集吧!示例表: SELECT * FROM tableA CROSS APPLY tableB 两张表直接连接,不需要任何的关联条件,产生 ...
- Java容器类List、ArrayList、Vector及map、HashTable、HashMap的区别与用法
Java容器类List.ArrayList.Vector及map.HashTable.HashMap的区别与用法 ArrayList 和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数 ...
- 转 Java中final、finally、finalize的区别与用法
Java中final.finally.finalize的区别与用法 1.简单区别:final用于声明属性,方法和类,分别表示属性不可交变,方法不可覆盖,类不可继承.finally是异常处理语句结构 ...
- Position属性四个值:static、fixed、absolute和relative的区别和用法
Position属性四个值:static.fixed.absolute和relative的区别和用法 在用CSS+DIV进行布局的时候,一直对position的四个属性值relative,absolu ...
- Python中内置数据类型list,tuple,dict,set的区别和用法
Python中内置数据类型list,tuple,dict,set的区别和用法 Python语言简洁明了,可以用较少的代码实现同样的功能.这其中Python的四个内置数据类型功不可没,他们即是list, ...
随机推荐
- Appium自动化测试教程-自学网-安卓模拟器
安卓模拟器: 夜神模拟器安装配置 下载地址:https://www.yeshen.com 开启VT VT是什么?为什么要开启VT? VT,全称是Virtualization Technology,即是 ...
- Oracle 数据库SQL审计
在我们日常的工作中,一些安全性的要求高的数据库需要增加审计操作,哪个用户什么时间做了什么操作. 1.打开数据库的审计 alter system set audit_sys_operations=TRU ...
- [Luogu] 程序自动分析
题面:https://www.luogu.org/problemnew/show/P1955 题解:https://www.zybuluo.com/wsndy-xx/note/1143858
- P3979 遥远的国度 树剖
P3979 遥远的国度 树剖 题面 需要想一下的树剖题,对于询问三需要处理换跟后的情况.我们以1为树根跑一遍剖分,对于换跟进行分类讨论,算出实际答案.讨论有三种情况: (以1为树根的树上) 跟在询问节 ...
- thinphp5.1 使用redis作为缓存
tp自带的cache类支持redis方式.但是 只有string类型.显然不符合我们的日常的业务需求. so.通过查看源码,发现 handler方法.代码见下图 所以, 这样就能用hash list等 ...
- ListCtrl 技巧集
1. ListCtrl 风格 LVS_ICON: 为每个item显示大图标 LVS_SMALLICON: 为每个item显示小图标 LVS_LIST: 显示一列带有 ...
- 如何使用纯js实现一个带有灰色半透明背景的弹出框
原文如何使用纯js实现一个带有灰色半透明背景的弹出框 // 加入透明背景 var body = document.body;var backgroundDiv = document.createEle ...
- flutter 中 List 和 Map 的用法
list集合 在Dart中,数组是List对象,因此大多数人只是将它们称为List.以下是一个简单的Dart的List: 创建一个int类型的list List list = [10, 7, 23]; ...
- Js 实现页面缩放
分享一个很棒的东西::::: 优点:不用考虑适配问题,按设计稿进行固定尺寸开发. 1.将下面这段 js 放在页面的<head>中 function bodyScale() { var de ...
- mysqldump定时任务生成备份文件内容为空解决方法
1问题:写好了一个mysqldump备份脚本(如图)直接执行可以正常生成备份文件,但在用crontab运行时却生成内容为空 2原因分析:由于mysqldump存在于全局环境变量mysql的bin下面, ...
