open函数的flag详解2

1、打开不存在的文件时:O_CREAT、O_EXCL
(1)思考:当我们去打开一个并不存在的文件时会怎样?当我们open打开一个文件时如果这个文件名不存在则会打开文件错误。
(2)vi或者windows下的notepad++,都可以直接打开一个尚未存在的文件。
(3)open的flag O_CREAT就是为了应对这种打开一个并不存在的文件的。O_CREAT就表示我们当前打开的文件并不存在,我们是要去创建并且打开它。
(4)思考:当我们open使用了O_CREAT,但是文件已经存在的情况下会怎样?经过实验验证发现结果是报错。
(5)结论:open中加入O_CREAT后,不管原来这个文件存在与否都能打开成功,如果原来这个文件不存在则创建一个空的新文件,如果原来这个文件存在则会重新创建这个文件,原来的内容会被消除掉(有点类似于先删除原来的文件再创建一个新的)
(6)这样可能带来一个问题?我们本来是想去创建一个新文件的,但是把文件名搞错了弄成了一个老文件名,结果老文件就被意外修改了。我们希望的效果是:如果我CREAT要创建的是一个已经存在的名字的文件,则给我报错,不要去创建。
(7)这个效果就要靠O_EXCL标志和O_CREAT标志来结合使用。当这连个标志一起的时候,则没有文件时创建文件,有这个文件时会报错提醒我们。

(8)open函数在使用O_CREAT标志去创建文件时,可以使用第三个参数mode来指定要创建的文件的权限。mode使用4个数字来指定权限的,其中后面三个很重要,对应我们要创建的这个文件的权限标志。譬如一般创建一个可读可写不可执行的文件就用0666


2、O_NONBLOCK
(1)阻塞与非阻塞。如果一个函数是阻塞式的,则我们调用这个函数时当前进程有可能被卡住(阻塞住,实质是这个函数内部要完成的事情条件不具备,当前没法做,要等待条件成熟),函数被阻塞住了就不能立刻返回;如果一个函数是非阻塞式的那么我们调用这个函数后一定会立即返回,但是函数有没有完成任务不一定。
(2)阻塞和非阻塞是两种不同的设计思路,并没有好坏。总的来说,阻塞式的结果有保障但是时间没保障;非阻塞式的时间有保障但是结果没保障。
(3)操作系统提供的API和由API封装而成的库函数,有很多本身就是被设计为阻塞式或者非阻塞式的,所以我们应用程度调用这些函数的时候心里得非常清楚。
(4)我们打开一个文件默认就是阻塞式的,如果你希望以非阻塞的方式打开文件,则flag中要加O_NONBLOCK标志。

(2)只用于设备文件,而不用于普通文件。

note:在openPLC项目中,当读串口设备的read函数是非阻塞的,然后使用select函数对设备文件进行定时监控,如果在规定时间内有内容可读则立马返回,然后进行read操作,如果超时或发生错误则返回0和-1。这样做的好处就是不需要一直阻塞在read,也不会一检测没有数据就立马返回。select允许read有一定的等待时间。

3、O_SYNC
(1)write阻塞等待底层完成写入才返回到应用层。

(2)无O_SYNC时write只是将内容写入底层缓冲区即可返回,然后底层(操作系统中负责实现open、write这些操作的那些代码,也包含OS中读写硬盘等底层硬件的代码)在合适的时候会将buf中的内容一次性的同步到硬盘中。这种设计是为了提升硬件操作的性能和销量,提升硬件寿命;但是有时候我们希望硬件不好等待,直接将我们的内容写入硬盘中,这时候就可以用O_SYNC标志。

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <error.h>
int main(int argc,char *argv[])
{
	int fd = 1;
	char buf[100] = {0};
	char wbuf[20] = {"I love linux."};
	int ret = -1;
	fd = open("a.txt",O_RDONLY |  O_CREAT | 	O_EXCL ,0666);
	
	if(-1 == fd ) //fd < 0
	{
		printf("File Open Error.\n");
		perror("open");
		_exit(-1);
	}
	else
	{
		printf("File Open Succeed. fd = %d\n",fd);
	}
	
	ret = write(fd,wbuf,strlen(wbuf));
	if(ret < 0)
	{
		printf("Write Error.\n");
		perror("write");
		_exit(-1);
	}
	else
	{
		printf("write %d byte.\n",ret);
		printf("write context is [%s]\n",wbuf);
	}

	ret = read(fd,buf,30);
        if(-1 == ret)
        {
                printf("Read Error.\n");
		perror("read");
		_exit(-1);
        }
        else
        {
                printf("read %d byte.\n",ret);
                printf("The context is [%s]\n",buf);
        }

	close(fd);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/a249093278/article/details/80940352