深入解读:Linux中o_creat参数的作用 (linux o creat)

在Linux系统下,我们常常需要创建文件,而Linux提供了一些系统调用来实现这一功能。其中open()是一个常用的系统调用,它可以打开一个文件,并返回一个文件描述符,供进程对该文件进行读写操作。open()系统调用的第二个参数flags是一个标志位参数,用于控制打开文件的行为和属性,其中包括o_creat参数,本文将详细解读这一参数的作用。

1. o_creat参数的基本使用

o_creat参数的作用是在打开文件时,如果文件不存在,则创建一个新文件。该参数可以与其他标志位参数组合使用,从而实现不同的功能。下面是一些基本用法:

1.1 打开已存在的文件

用法:open(filename, flags)

这个用法与不使用o_creat参数的效果一样,只会打开已存在的文件,并返回对应的文件描述符。

1.2 创建新的文件并写入数据

用法:open(filename, O_CREAT | O_WRON, mode)

这个用法将新建一个文件,并将mode参数赋予其指定的文件权限,同时打开文件并将数据写入其中。其中O_CREAT参数代表如果文件不存在,则创建新文件,O_WRON参数代表只写模式,即仅仅允许写入数据。

1.3 读取文件并创建新的文件

用法:open(filename, O_CREAT | O_WRON | O_TRUNC, mode)

这个用法将打开旧文件并从中读取数据,同时也会新建一个文件,并将mode参数赋予其指定的文件权限。O_CREAT参数表示如果文件不存在,则创建新文件,O_WRON参数代表只写模式,O_TRUNC参数表示在打开文件时清空文件内容。

2. o_creat参数的高级用法

o_creat参数不仅可以在基本用法中发挥作用,还可以与其他标志位参数进行组合,从而实现更复杂的功能。

2.1 设置文件的访问权限

用法:open(filename, O_CREAT | O_EXCL | O_WRON, mode)

在新建文件时,如果文件已存在则不执行任何写入操作,并返回错误。如果文件不存在,则创建新文件,并用指定的mode参数赋予其指定的文件读写权限。O_EXCL参数表示如果文件已存在,则不会执行创建操作。

2.2 保留原文件属性并保存文件

用法:open(filename, O_CREAT | O_EXCL | O_WRON | O_NOFOLLOW, mode)

在新建文件时,如果文件已存在则不执行任何写入操作,并返回错误。如果文件不存在,则创建新文件,并用指定的mode参数赋予其指定的文件读写权限。O_EXCL参数表示如果文件已存在,则不会执行创建操作。O_NOFOLLOW参数表示只能打开符号链接,不能打开其他文件类型。

2.3 写入数据到文件末尾

用法:open(filename, O_CREAT | O_EXCL | O_WRON | O_APPEND, mode)

在新建文件时,如果文件已存在则不执行任何写入操作,并返回错误。如果文件不存在,则创建新文件,并在文件尾部添加新数据。O_EXCL参数表示如果文件已存在,则不会执行创建操作。O_APPEND参数表示在文件末尾添加数据。

3.

在Linux系统中,o_creat参数是open()系统调用中的一个标志位参数,用于控制文件的创建和打开行为。它提供了许多高级用法,可以与其他标志位参数组合使用,从而实现更复杂的功能。深入了解o_creat参数及其相关用法,有助于开发人员更好地控制文件创建及打开行为,提高系统开发效率,确保文件安全性。

相关问题拓展阅读:

  • <a href="#linux下一程序 if(destfd=open("ilu.txt",O_RDWR|O_CREATE,0666))” title=”linux下一程序 if(destfd=open(“ilu.txt”,O_RDWR|O_CREATE,0666))”>linux下一程序 if(destfd=open(“ilu.txt”,O_RDWR|O_CREATE,0666))
  • linux文件锁定被使用
  • Linux信号量

<h3 id="linux下一程序 if(destfd=open("ilu.txt",O_RDWR|O_CREATE,0666))”>linux下一程序 if(destfd=open(“ilu.txt”,O_RDWR|O_CREATE,0666))

mode标志激空不是5位哦岁答,0666代表打开权限,

linux下分别有user,group,other等几种权限

user有S_IRUSR,S_IWUSR,S_IXUSR,分别代表read,write,exute(读写执行)的权限用二进制表示成100,010,001所以6就等于100+010,明雀瞎可以表示成S_IRUSR|S_IWUSR,以此类推

GRP有S_IRGRP,S_IWGRP,S_IXGRP

other有S_IROTH,S_IWOTH,S_IXOTH

当然linux还有设置权限位可以设置为 S_ISUSR或者S_ISOTH

所以呢0666 = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH

我一般是这么写的,要包上头文件 sys/stat.h

楼主你好!

那你说的是open()函数中的mode_t mode吧?

mode参数激并念只有在建立新文件时才会生效(flags中包含O_CREAT),表示新建文件的权限,但最终所建文件的权明困限会受到umask值所影响,因此该文件权限应该为(mode-umaks)。

666表示为rw-rw-rw-,即,对于用户、组、其他都对该文件有读写权,没有执行权!蔽哗

可以通过终端命令行ls -l可以查看的!

希望我的回答对你有帮助!

linux文件锁定被使用

一、什么是文件锁定

对于锁这个字,大家一定不会陌生,因为我们生活中就存在着大量的锁,它们各个方面发挥着它的作用,现在世界中的锁的功能都可归结为一句话,就是阻止某些人做某些事,例如,门锁就是阻止除了屋主之外的人进入这个房子,你进入不到这个房子,也就不能使用房子里面的东西。

而因为程序经常需要共享数据,而这通常又是通过文件来实现的,试想一个情况,A进程正在对一个文件进行写操作,而另一个程序B需要对同一个文件进行读操作,并以读取到的数据作为自己凳悉改程序运行时所需要的数据,这会发生什么情况呢?进程B可能会读到错乱的数据,因为它并不知道另一个进程A正在改写这个文件中的数据。

为了解决类似的问题,就出现了文件锁定,简单点来说,这是文件的一种安全的更新方式,当一个程序正在对文件进行写操作时,文件就会进入一种暂时状态,在这个状态下,如果另一个程序尝试读这个文件,它就会自动停下来等待这个状态结束。Linux系统提供了很多特性来实现文件锁定,其中最简单的方法就是以原子操作的方式创建锁文件。

用回之前的例子就是,文件锁就是当文件在写的时候,阻止其他的需要写或者要读文件的进程来操作这个文件。

二、创建锁文件

创建一个锁文件是非常简单的,我们可以使用open系统调用来创建一个锁文件,在调用open时oflags参数要增加参数O_CREAT和O_EXCL标志,如file_desc = open(“/tmp/LCK.test”, O_RDWR|O_CREAT|O_EXCL, 0444);就可以创建一个锁文件/tmp/LCK.test。O_CREAT|O_EXCL,可以确保调用者可以创建出文件,使用这个模式可以防止两个程序同时创建同一个文件,如果文件(/tmp/LCK.test)已经存在,则open调用就会失败,返回-1。

如果一个程序在它执行时,只需要独占某个资源一段很短的时间,这个时间段(或代码区)通常被叫做临界区,陆埋我们需要在进入临界区之前使用open系统调用创建锁文件,然后在退出临界区时用unlink系统调用删除这个锁文件。

注意:锁文件只是充当一个指示器的角色,程序间需要通过相互协作来使用它们,也就是说锁文件只是建议锁,而不是强制锁,并不会真正阻止你读写文件中的数据。

可以看看下面的例子:源文件文件名为filelock1.c,代码如下:

#include #include #include #include #include int main() { const char *lock_file = “/tmp/LCK.test1”; int n_fd = -1; int n_tries = 10; while(n_tries–) { //创建锁文件 n_fd = open(lock_file, O_RDWR|O_CREAT|O_EXCL, 0444); if(n_fd == -1) { //创建失败 printf(“%d – Lock already present “, getpid()); sleep(2); } else { //创建成功 printf(“%d – I have exclusive access “, getpid()); sleep(1); close(n_fd); //删除锁文件,释放锁 unlink(lock_file); sleep(2); } } return 0; }

同时运行同一个程序的两个实例,运行结果为:

从运行的结果可以看出两个程序交叉地对对文件进行锁定,但是真实的操作却是,每次调用open函数去检查/tmp/LCK.test1这个文件是否存在,如果存在open调用就失败,显示有进程已经把这个文件锁定了,如果这个文件不存在,就创建这个文件,并显示许可信息。但是这种做法有一定的缺憾,我们可以看到文件/tmp/LCK.test1被创建了很多次,也被unlink删除了很多次,也就是说我们不能使用已经事先有数据的文件作为这种锁文件,因为如果文件已经存在,则open调用总是失败。

给我的感觉是,这枣判更像是一种对进程工作的协调性安排,更像是二进制信号量的作用,文件存在为0,不存在为1,而不是真正的文件锁定。

三、区域锁定

我们还有一个问题,就是如果同一个文件有多个进程需要对它进行读写,而一个文件同一时间只能被一个进程进行写操作,但是多个进程读写的区域互不相关,如果总是要等一个进程写完其他的进程才能对其进行读写,效率又太低,那么是否可以让多个进程同时对文件进行读写以提高数据读写的效率呢?

为了解决上面提到的问题,和出现在第二点中的问题,即不能把文件锁定到指定的已存在的数据文件上的问题,我们提出了一种新的解决方案,就是区域锁定。

简单点来说,区域锁定就是,文件中的某个部分被锁定了,但其他程序可以访问这个文件中的其他部分。

然而,区域锁定的创建和使用都比上面说的文件锁定复杂很多。

1、创建区域锁定

在Linux上为实现这一功能,我们可以使用fcntl系统调用和lockf调用,但是下面以fcntl系统调用来讲解区域锁定的创建。

fctnl的函数原理为:

int fctnl(int fildes, int command, …);

它对一个打开的文件描述进行操作,并能根据command参数的设置完成不同的任务,它有三个可选的任务:F_GETLK,F_SETLK,F_SETLKW,至于这三个参数的意义下面再详述。而当使用这些命令时,fcntl的第三个参数必须是一个指向flock结构的指针,所以在实际应用中,fctnl的函数原型一般为:int fctnl(int fildes, int command, struct flock *flock_st);

2、flock结构

准确来说,flock结构依赖具体的实现,但是它至少包括下面的成员:

short l_type;文件锁的类型,对应于F_RDLCK(读锁,也叫共享锁),F_UNLCK(解锁,也叫清除锁),F_WRLCK(写锁,也叫独占锁)中的一个。

short l_whence;从文件的哪个相对位置开始计算,对应于SEEK_SET(文件头),SEEK_CUR(当前位置),SEEK_END(文件尾)中的一个。

off_t l_start;从l_whence开始的第l_start个字节开始计算。

off_t l_len;锁定的区域的长度。

pid_t l_pid;用来记录参持有锁的进程。

成员l_whence、l_start和l_len定义了一个文件中的一个区域,即一个连续的字节,例如:

struct flock region;

region.l_whence = SEEK_SET;

region.l_start = 10;

region.l_len = 20;

则表示fcntl函数操作锁定的区域为文件头开始的第10到29个字节之间的这20个字节。

3、文件锁的类型

从上面的flock的成员l_type的取值我们可以知道,文件锁的类型主要有三种,这里对他们进行详细的解说。

F_RDLCK:

从它的名字我们就可以知道,它是一个读锁,也叫共享锁。许多不同的进程可以拥有文件同一(或重叠)区域上的读(共享)锁。而且只要任一进程拥有一把读(共享)锁,那么就没有进程可以再获得该区域上的写(独占)锁。为了获得一把共享锁,文件必须以“读”或“读/写”方式打开。

简单点来说就是,当一个进程在读文件中的数据时,文件中的数据不能被改变或改写,这是为了防止数据被改变而使读数据的程序读取到错乱的数据,而文件中的同一个区域能被多个进程同时读取,这是容易理解的,因为读不会破坏数据,或者说读操作不会改变文件的数据。

F_WRLCK:

从它的名字,我们就可以知道,它是一个写锁,也叫独占锁。只有一个进程可以在文件中的任一特定区域拥有一把写(独占)锁。一旦一个进程拥有了这样一把锁,任何其他进程都无法在该区域上获得任何类型的锁。为了获得一把写(独占)锁,文件也必须以“读”或“读/写”方式打开。

简单点来说,就是一个文件同一区域(或重叠)区域进在同一时间,只能有一个进程能对其进行写操作,并且在写操作进行期间,其他的进程不能对该区域进行读取数据。这个要求是显然易见的,因为如果两个进程同时对一个文件进行写操作,就会使文件的内容错乱起来,而由于写时会改变文件中的数据,所以它也不允许其他进程对文件的数据进行读取和删除文件等操作。

F_UNLCK:

从它的名字就可以知道,它用于把一个锁定的区域解锁。

4、不同的command的意义

在前面说到fcntl函数的command参数时,说了三个命令选项,这里将对它们进行详细的解说。

F_GETLK命令,它用于获取fildes(fcntl的之一个参数)打开的文件的锁信息,它不会尝试去锁定文件,调用进程可以把自己想创建的锁类型信息传递给fcntl,函数调用就会返回将会阻止获取锁的任何信息,即它可以测试你想创建的锁是否能成功被创建。fcntl调用成功时,返回非-1,如果锁请求可以成功执行,flock结构将保持不变,如果锁请求被阻止,fcntl会用相关的信息覆盖flock结构。失败时返回-1。

所以,如果调用成功,调用程序则可以通过检查flock结构的内容来判断其是否被修改过,来检查锁请求能否被成功执行,而又因为l_pid的值会被设置成拥有锁的进程的标识符,所以大多数情况下,可以通过检查这个字段是否发生变化来判断flock结构是否被修改过。

使用F_GETLK的fcntl函数调用后会立即返回。

举个例子来说,例如,有一个flock结构的变量,flock_st,flock_st.l_pid = -1,文件的第10~29个字节已经存在一个读锁,文件的第40~49个字节中已经存在一个写锁,则调用fcntl时,如果用F_GETLK命令,来测试在第10~29个字节中是否可以创建一个读锁,因为这个锁可以被创建,所以,fcntl返回非-1,同时,flock结构的内容也不会改变,flock_st.l_pid = -1。而如果我们测试第40~49个字节中是否可以创建一个写锁时,由于这个区域已经存在一个写锁,测试失败,但是fcntl还是会返回非-1,只是flock结构会被这个区域相关的锁的信息覆盖了,flock_st.l_pid为拥有这个写锁的进程的进程标识符。

F_SETLK命令,这个命令试图对fildes指向的文件的某个区域加锁或解锁,它的功能根据flock结构的l_type的值而定。而对于这个命令来说,flock结构的l_pid字段是没有意义的。如果加锁成功,返回非-1,如果失败,则返回-1。使用F_SETLK的fcntl函数调用后会立即返回。

F_SETLKW命令,这个命令与前面的F_SETLK,命令作用相同,但不同的是,它在无法获取锁时,即测试不能加锁时,会一直等待直到可以被加锁为止。

5、例子

看了这么多的说明,可能你已经很乱了,就用下面的例子来整清你的思想吧。

源文件名为filelock2.c,用于创建数据文件,并将文件区域加锁,代码如下:

#include #include #include #include int main() { const char *test_file = “test_lock.txt”; int file_desc = -1; int byte_count = 0; char *byte_to_write = “A”; struct flock region_1; struct flock region_2; int res = 0; //打开一个文件描述符 file_desc = open(test_file, O_RDWR|O_CREAT, 0666); if(!file_desc) { fprintf(stderr, “Unable to open %s for read/write “, test_file); exit(EXIT_FAILURE); } //给文件添加100个‘A’字符的数据 for(byte_count = 0; byte_count #include #include #include int main() { const char *test_file = “test_lock.txt”; int file_desc = -1; int byte_count = 0; char *byte_to_write = “A”; struct flock region_1; struct flock region_2; int res = 0; //打开数据文件 file_desc = open(test_file, O_RDWR|O_CREAT, 0666); if(!file_desc) { fprintf(stderr, “Unable to open %s for read/write “, test_file); exit(EXIT_FAILURE); } //设置区域1的锁类型 struct flock region_test1; region_test1.l_type = F_RDLCK; region_test1.l_whence = SEEK_SET; region_test1.l_start = 10; region_test1.l_len = 20; region_test1.l_pid = -1; //设置区域2的锁类型 struct flock region_test2; region_test2.l_type = F_RDLCK; region_test2.l_whence = SEEK_SET; region_test2.l_start = 40; region_test2.l_len = 10; region_test2.l_pid = -1; //

三、解空锁问题

如果我要给在本进程中没有加锁的区域解锁会发生什么事情呢?而如果这个区域中其他的进程有对其进行加锁又会发生什么情况呢?

如果一个进程实际并未对一个区域进行锁定,而调用解锁操作也会成功,但是它并不能解其他的进程加在同一区域上的锁。也可以说解锁请求最终的结果取决于这个进程在文件中设置的任何锁,没有加锁,但对其进行解锁得到的还是没有加锁的状态。

Linux信号量

信号量是包含一个非负整数型的变量,并且带有两个原子操作wait和signal。Wait还可以被称为down、P或lock,signal还可以被称为up、V、unlock或post。在UNIX的API中(POSIX标准)用的是wait和post。

对于wait操作,如果信号量的非负整形变量S大于0,wait就将其减1,如果S等于0,wait就将调用线程阻塞;对于post操作,如果有线程在信号量上阻塞(此时S等于0),post就会解除对某个等待线程的阻塞,使其从wait中返回,如果没有线程阻塞在信号量上,post就将S加1.

由此可见,S可以被理解为一种资源的数量,信号量即是通过控制这种资源的分配来实现互斥和同步的。如果把S设为1,那么信号量即可使多线程并发运行。另外,信号量不仅允许使用者申请和释放资源,而且还允许使用者创竖哗造资源,这就赋予了信号量实现同步的功能。可见信号量的功能要比互斥量丰富许多。

POSIX信号量是一个sem_t类型的变量,但POSIX有两种信号量的实现机制:

无名信号量

命名信号量

。无名信号量只可以在共享内存的情况下,比如实现进程中各个线程之间的互斥和同步,因此无名信号量也被称作基于内存的信号量;命名信号量通常用于不共享内存的情况下,比如进程间通信。

同时,在创建信号量时,根据信号量取值的不同,POSIX信号量还可以分为:

下面是POSIX信号量函数接口:

信号量的函数都以sem_开头,线程中使用的基本信号函数有4个,他们都声明在头文件semaphore.h中,该头文件定义了用于信号量操作的sem_t类型:

【sem_init函数】:

该函数用于创猜型建信号量,原型如下:

该函数初始化由sem指向的余兆行信号对象,设置它的共享选项,并给它一个初始的整数值。pshared控制信号量的类型,如果其值为0,就表示信号量是当前进程的局部信号量,否则信号量就可以在多个进程间共享,value为sem的初始值。

该函数调用成功返回0,失败返回-1。

【sem_destroy函数】:

该函数用于对用完的信号量进行清理,其原型如下:

成功返回0,失败返回-1。

【sem_wait函数】:

该函数用于以原子操作的方式将信号量的值减1。原子操作就是,如果两个线程企图同时给一个信号量加1或减1,它们之间不会互相干扰。其原型如下:

sem指向的对象是sem_init调用初始化的信号量。调用成功返回0,失败返回-1。

sem_trywait()则是sem_wait()的非阻塞版本,当条件不满足时(信号量为0时),该函数直接返回EAGAIN错误而不会阻塞等待。

sem_timedwait()功能与sem_wait()类似,只是在指定的abs_timeout时间内等待,超过时间则直接返回ETIMEDOUT错误。

【sem_post函数】:

该函数用于以原子操作的方式将信号量的值加1,其原型如下:

与sem_wait一样,sem指向的对象是由sem_init调用初始化的信号量。调用成功时返回0,失败返回-1。

【sem_getvalue函数】:

该函数返回当前信号量的值,通过restrict输出参数返回。如果当前信号量已经上锁(即同步对象不可用),那么返回值为0,或为负数,其绝对值就是等待该信号量解锁的线程数。

【实例1】:

【实例2】:

之所以称为命名信号量,是因为它有一个名字、一个用户ID、一个组ID和权限。这些是提供给不共享内存的那些进程使用命名信号量的接口。命名信号量的名字是一个遵守路径名构造规则的字符串。

【sem_open函数】:

该函数用于创建或打开一个命名信号量,其原型如下:

参数name是一个标识信号量的字符串。参数oflag用来确定是创建信号量还是连接已有的信号量。

oflag的参数可以为0,O_CREAT或O_EXCL:如果为0,表示打开一个已存在的信号量;如果为O_CREAT,表示如果信号量不存在就创建一个信号量,如果存在则打开被返回,此时mode和value都需要指定;如果为O_CREAT|O_EXCL,表示如果信号量存在则返回错误。

mode参数用于创建信号量时指定信号量的权限位,和open函数一样,包括:S_IRUSR、S_IWUSR、S_IRGRP、S_IWGRP、S_IROTH、S_IWOTH。

value表示创建信号量时,信号量的初始值。

【sem_close函数】:

该函数用于关闭命名信号量:

单个程序可以用sem_close函数关闭命名信号量,但是这样做并不能将信号量从系统中删除,因为命名信号量在单个程序执行之外是具有持久性的。当进程调用_exit、exit、exec或从main返回时,进程打开的命名信号量同样会被关闭。

【sem_unlink函数】:

sem_unlink函数用于在所有进程关闭了命名信号量之后,将信号量从系统中删除:

【信号量操作函数】:

与无名信号量一样,操作信号量的函数如下:

命名信号量是随内核持续的。当命名信号量创建后,即使当前没有进程打开某个信号量,它的值依然保持,直到内核重新自举或调用sem_unlink()删除该信号量。

无名信号量的持续性要根据信号量在内存中的位置确定:

很多时候信号量、互斥量和条件变量都可以在某种应用中使用,那这三者的差异有哪些呢?下面列出了这三者之间的差异:

关于linux o creat的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。


数据运维技术 » 深入解读:Linux中o_creat参数的作用 (linux o creat)