GVKun编程网logo

linux fork() fcntl() 供使用(linux fork vfork)

2

想了解linuxfork()fcntl()供使用的新动态吗?本文将为您提供详细的信息,我们还将为您解答关于linuxforkvfork的相关问题,此外,我们还将为您介绍关于fcntl与NFS、fcnt

想了解linux fork() fcntl() 供使用的新动态吗?本文将为您提供详细的信息,我们还将为您解答关于linux fork vfork的相关问题,此外,我们还将为您介绍关于fcntl 与 NFS、fcntl 函数用法 —— 操纵文件描述符状态、fcntl,lockf,哪个更适合用于文件锁定?、ioctl() fcntl() setsockopt() ioctlsocket() 用法的新知识。

本文目录一览:

linux fork() fcntl() 供使用(linux fork vfork)

linux fork() fcntl() 供使用(linux fork vfork)

如何解决linux fork() fcntl() 供使用

我正在研究多进程 fcntl()。 子进程共享文件描述符。 我只想让文件可以访问其中一个子进程,而其他子进程则无法访问。

首先创建三个子进程,打开文件描述符。

for(int i=0;i<3;i++)
     pid=fork()
     if(pid==0)
        fd = open("ACCOUNT_FILE",....);

在文件中记录锁定 将钱存入账户。 我想让文件描述符只能访问一个进程。 请帮帮我。

reclock(fd,acccount_number,sizeof(struct record),F_WRLCK);
pos = acccount_number * sizeof(struct record);
lseek(fd,pos,SEEK_SET);
n = read(fd,&cur,sizeof(struct record));
cur.balance += amount;
lseek(fd,SEEK_SET);
write(fd,sizeof(struct record));
reclock(fd,F_UNLCK);
void reclock(int fd,int recno,int len,int type)
{   
    struct flock fl;
    switch(type){
     case F_RDLCK;
     case F_WRLCK;
     case F_UNLOCK;
         fl.l_type=type;
         fl.l_whence=SEEK_SET;
         fl.l_start=recno*len;
         fl.l_len=len;
         fcntl(fd,F_SETLKW,&fl);
         return1;
     default:  return–1;
    };
}

fcntl 与 NFS

fcntl 与 NFS

   对文件进行flock加独占锁时,只对本机文件起作用,且只对两人达成这个"协商"的程序起作用.  而通过RPC Service的访问,flock是不起作用的. 这个时候 如果你使用man flock.帮助中会有 

flock() does not lock files over NFS. Use fcntl(2) instead: that does work over NFS, given a sufficiently recent version of Linux and a server which supports locking.

这么一句. 也就是说 flock不支持,可以通过fcntl这个函数来代替. 

Install NFS 

Fedora 可以通过 yum install portmap nfs-utils 来进行安装

安装好后进行配置 etc/exports 

/opt 192.168.153.164(rw,sync,no_root_squash)

/opt  共享目录

192.168.153.164 为运行mount的主机IP

rw-> 读写权限, sync实时写入硬盘 async 先写入内存再写入硬盘, no_root_squash->开放root身份

保存,然后重新启动nfs :

/etc/rc.d/init.d/nfs restart

如果没有都OK 建议再次restart 或者对重启机子.

然后客户端主机就可以使用mount命令对其进行mount了.我们来写个fcntl的程序测试下.

1 #include <Akita/Akita.h>
  2 #include <sys/file.h>
  3 #include <fcntl.h>
  4 #include <unistd.h>
  5 #include <sys/types.h>
  6 #include <sys/stat.h>
  7 int main(int argc, const char *argv[])
  8 {
  9     int fd = open("./main.c", O_RDWR);
 10     if (fd<0) {
 11         printf("%s\n","Open File error!");
 12     }
 13     //int ld = flock(fd, LOCK_EX);
 14     struct flock lock;
 15     lock.l_whence = SEEK_SET;
 16     lock.l_start = 0;
 17     lock.l_len = 0;
 18     lock.l_type = F_WRLCK;
 19     int fld = fcntl(fd, F_SETLK, &lock);
 20     printf("FCNTL ret = %d\n", fld);
 21     if (fld == 0) {
 22         if (lock.l_type == F_WRLCK) {
 23             printf("WRLCK PID = %d\n", getpid());
 24 
 25         }
 26 
 27     }
 28     getchar();
 29     return 0;
 30 }
本机运行 此程序生成的一个目标程序, 程序会正常返回:

^_^[root@:/opt]#./a.out 
FCNTL ret = 0
WRLCK PID = 4391

另外一台mount过来的目录中运行一个目标程序:

^_^[root@:/home/crazybaby/A]#./b.out 
FCNTL ret = -1

若先运行mount过来的程序,记录锁也会生效的.



原文链接: http://blog.csdn.net/crazyjixiang/article/details/6939192

fcntl 函数用法 —— 操纵文件描述符状态

fcntl 函数用法 —— 操纵文件描述符状态

fcntl 函数:操纵文件描述符,改变已经打开的文件的属性
int fcntl(int fd, int cmd, ... //arg  );
cmd 选项:
一、复制文件描述符:F_DUPFD
二、更改设置文件描述标志:F_GETFD 、F_SETFD  文件描述符标志,是体现进程的文件描述符的状态.
当前只定义了一个文件描述符标志 FD_CLOEXEC。
   0: exec 时不关闭已经打开的文件描述符
   1: exec 时关闭已经打开的文件描述符

三、获取或者设置文件状态标识:F_GETFL、 F_SETFL (读写追加阻塞等等)
    文件状态标签中的标志可分为三类:访问方式、打开时标志和 I/O 操作方式。
 1. 访问方式 访问方式指明允许文件描述字用于读、写或两者兼之,包括 O_RDONLY、O_WRONLY 和 O_RDWR。
这些访问方式在文件被打开时选定,之后便不能再改变。
 2、打开时标志指明打开文件时影响 open () 行为的一些选项。这些选项一旦文件打开就不保留,
但有一个例外是 O_NONBLOCK,因为 O_NONBLOCK 同时也是一个 I/O 操作方式,故此标志被保留例如:O_CREAT
 3、I/O 操作方式:I/O 操作方式影响使用文件描述字进行输入输出操作的工作方式。这些标志由 open () 设置,
之后可以用 fcntl () 获取和改变。O_APPEND、O_NONBLOCK、O_SYNC 等
四、设置获取文件锁:F_GETLK、F_SETLK,F_SETLKW

 

 1 #include<unistd.h>
 2 #include<sys/types.h>
 3 #include<sys/stat.h>
 4 #include<fcntl.h>
 5 #include<stdlib.h>
 6 #include<stdio.h>
 7 #include<errno.h>
 8 #include<string.h>
 9 #define ERR_EXIT(m)\
10     do\
11     {\
12         perror(m);\
13         exit(EXIT_FAILURE);\
14     }while(0)  //宏要求一条语句
15 void set_flags(int fd,int flags);
16 void clr_flags(int fd,int flags);
17 int main(int argc,char*argv[])
18 {
19     char buf[1024]={0};
20     int ret;
21 /*    flags=fcntl(0,F_GETFL,0);//先获取标准输入的标志
22     if(flags==-1)
23         ERR_EXIT("fcntl get flags error");
24     ret=fcntl(0,F_SETFL,flags|O_NONBLOCK);//将标准输入设置为非阻塞,默认对读是阻塞的。不更改其他状态
25     if(ret==-1)
26         ERR_EXIT("fcntl set flags error");
27 */    set_flags(0,O_NONBLOCK);//设置非阻塞,直接返回   (EAGIAN)read error: Resource temporarily unavailable(资源暂且不可用),如果是socket,会返回EWOUDBOCK
28     //clr_flags(0,O_NONBLOCK);//清除
29     ret=read(0,buf,1024);//标准输入读,read标准输入0默认阻塞(文件状态标志)
30     if(ret==-1)
31         ERR_EXIT("read error");
32     printf("buf=%s\n",buf);
33     return 0;
34 }
35 void set_flags(int fd,int flags)
36 {
37     int val;
38     val=fcntl(fd,F_GETFL,0);//先获取标准输入的标志
39     if(val==-1)
40         ERR_EXIT("fcntl get flags error");
41     val |=flags;
42     if(fcntl(fd,F_SETFL,val)<0)
43         ERR_EXIT("fcntl set flags error");
44 }
45 void clr_flags(int fd,int flags)//清除状态
46 {
47     int val;
48     val=fcntl(fd,F_GETFL,0);//先获取标准输入的标志
49     if(val==-1)
50         ERR_EXIT("fcntl get flags error");
51     val&=(~flags);//原状态中与上 flags 的反
52     if(fcntl(fd,F_SETFL,val)<0)
53         ERR_EXIT("fcntl set flags error");
54 }

 

下面的例子讲解 fcntl 更改设置文件描述标志:

 1 //hello.c
 2 #include<unistd.h>
 3 #include<stdio.h>
 4 //hello程序打印程序环境变量
 5 extern char** environ;//指针的指针,指向一个指针数组 environ-->[...]数组中每一项指向一个环境信息。例如"TERM=VI00","SHELL=/bin/bash"
 6 int main(void)
 7 {
 8     printf("hello pid=%d\n",getpid());
 9     //打印环境变量
10     int i;
11     for(i=0;environ[i]!=NULL;i++)
12     {
13         printf("%s\n",environ[i]);
14     }
15     return 0;
16 }
17 
18 //ececlp.标准输出在execlp中已经关闭,无法使用
19 #include<unistd.h>
20 #include<sys/types.h>
21 #include<stdlib.h>
22 #include<stdio.h>
23 #include<errno.h>
24 #include<fcntl.h>
25 #define ERR_EXIT(m)\
26     do\
27     {\
28         perror(m);\
29         exit(EXIT_FAILURE);\
30     }while(0)  //宏要求一条语句
31 int main()
32 {
33     printf("Entering main...\n");
34     int flag=fcntl(1,F_GETFD);
35     int ret=fcntl(1,F_SETFD,flag|FD_CLOEXEC);//标准输出EXEC位置1
36     if(ret==-1)
37         perror("fcntl");
38     //使用exec执行的程序里,此描述符被关闭,不能再使用它
39     execlp("./hello","hello",NULL);//ececlp替换是成功的,但是标准输出EXEC位已经被置位,所以hello无法输出。
40 /*输出结果
41 Entering main...
42 */
43     printf("Exiting main...\n");//不输出了
44     return 0;
45 }

 

fcntl,lockf,哪个更适合用于文件锁定?

fcntl,lockf,哪个更适合用于文件锁定?

寻找有关 fcntl lockf优点缺点
的信息以进行文件锁定。例如,哪个更适合用于便携性?我目前正在编写linux守护程序,并想知道哪种守护程序更适合用于执行互斥。 __ __

答案1

小编典典

lockf和fcntl有什么区别:

在许多系统上,lockf()库例程只是的包装fcntl()。也就是说,lockf提供了该功能的子集fcntl

资源

但是,在某些系统上,fcntl并且lockf锁是完全独立的。

资源

由于它取决于实现,因此请确保始终使用相同的约定。因此,要么总是在两个进程中都使用lockf,要么总是使用fcntl。它们很可能会互换,但是使用相同的对象更安全。

选择哪一个都没关系。


关于强制锁和咨询锁的一些说明:

在UNIX锁定/ linux是默认 咨询
,意味着其他进程并不需要遵循所设置的锁定规则。因此,只要您的协作过程也使用相同的约定,锁定哪种方式都没有关系。

Linux确实支持 强制 锁定,但前提是您的文件系统在选项为on且文件特殊属性已设置的情况下挂载。您可以使用mount -omand挂载文件系统并设置文件属性g-x,g+s以启用强制性锁定,然后使用fcntllockf。有关强制锁如何工作的更多信息,请参见此处。

请注意,锁并不应用于单个文件,而是应用于索引节点。这意味着指向相同文件数据的2个文件名将共享相同的锁定状态。

另一方面,在Windows中,您可以主动以独占方式打开文件,这将阻止其他进程完全打开该文件。即使他们想要。即,锁是强制性的。Windows和文件锁也是如此。具有打开的文件句柄且具有适当访问权限的任何进程都可以锁定文件的一部分,并且其他进程将无法访问该部分。


强制锁如何在Linux中工作:

关于强制性锁,如果某个进程使用读取锁锁定文件的某个区域,则其他进程将被允许读取但不能写入该区域。如果某个进程使用写锁定锁定文件的区域,则不允许其他进程读取或写入该文件。不允许进程访问文件部分时,会发生什么情况取决于您是否指定O_NONBLOCK。如果设置了阻止,它将等待执行该操作。如果未设置阻止,则将收到错误代码EAGAIN


NFS警告:

如果在NFS挂载上使用锁定命令,请小心。该行为是不确定的,并且实现是广泛变化的,是仅使用本地锁定还是支持远程锁定。

ioctl() fcntl() setsockopt() ioctlsocket() 用法

ioctl() fcntl() setsockopt() ioctlsocket() 用法

int ioctl(int d, int request, ...); 后续是否有参数根据第二个参数request的需要来决定。

ioctl用于硬件设备I/O通道控制,控制命令与参数都与设备高度相关,通常也与系统高度相关。

int fcntl(int fd, int cmd, ... /* arg */ );后续是否有参数根据第二个参数cmd的需要来决定。这点两者相同。

操作控制的对象是: 文件描述符。

ioctl()是底层的系统调用(system call),所以跨平台特性不好。

而fcntl则是被封装的函数,各个OS都是支持的。

在网络socket中,他们作用大概相似。

例如都可以设置socket的是否允许非阻塞模式,不过设置方式上略有不同:

int socketfd = .....;

 fcntl(sockfd, F_SETFL,fcntl(sockfd, F_GETFL, 0) |O_NONBLOCK);


 ioctl(sockfd, FIONBIO,1);  1:非阻塞0:阻塞

int setsockopt(int sockfd, int level, int optname, void *optval,socklen_t *optlen); 
设置套接字选项.只能操作套接字。
 
 sockfd:    套接字
 level:     协议层  SOL_SOCKET/IPPROTO_IP/IPPRO_TCP
 optname:   选项名  每一个协议层都有其固定的选项名
 optval:    缓冲区  set是指向将要存放的地址, get是指向目前存放信息的地址
 optlen:    缓冲区大小长度

在socket层常用操作有:
SO_BROADCAST            允许发送广播数据                  int
SO_DEBUG        允许调试                int
SO_DONTROUTE      不查找路由               int
SO_ERROR        获得套接字错误             int
SO_KEEPALIVE      保持连接                int
SO_LINGER        延迟关闭连接              structlinger
SO_OOBINLINE      带外数据放入正常数据流         int
SO_RCVBUF        接收缓冲区大小             int
SO_SNDBUF        发送缓冲区大小             int
SO_RCVLOWAT       接收缓冲区下限             int
SO_SNDLOWAT       发送缓冲区下限             int
SO_RCVTIMEO       接收超时                structtimeval
SO_SNDTIMEO       发送超时                structtimeval
SO_REUSERADDR      允许重用本地地址和端口         int
SO_TYPE         获得套接字类型             int
SO_BSDCOMPAT      与BSD系统兼容              int

使用 SO_RECVBUF 和 SO_SENDBUF可以改变缺省缓冲区大小
 例:
  //设置接收缓冲区大小
  intn_recvbuf = 32 * 1024;
  setsockopt(sockfd, SOL_SOCKET,SO_RECVBUF, (const char*)&n_recvbuf,sizeof(int));
  
  //设置发送缓冲区大小
  intn_sendbuf = 32 * 1024;
  setsockopt(sockfd, SOL_SOCKDET,SO_SENDBUF, (const char*)&n_sendbuf,sizeof(int));
 
 使用SO_REUSERADDR:
  1.当有一个有相同本地地址和端口的socket1处于TIME_WAIT状态时,而你启动的程序的socket2要占用该地址和端口,你的程 序就要用到该选项。
  2.SO_RESUERADDR允许同一port上启动同一服务器的多个实例(多个进程),但每个实例绑定的IP地址是不能相同的。

  3.SO_RESUERADDR允许单个进程绑定相同的端口到多个socket上,但每个socket绑定的ip地址不同。

  4.SO_RESUERADDR允许完全相同的地址和端口的重复绑定,但这只用于UDP的多播,不用于TCP。
setsockopt()只是针对socket设置参数,是在连接中的参数控制,在OS层级的控制则由ioctl和fcntl控制。如果要是获取socket参数则使用getsockopt.
--------------------- 
作者:Richard__Lee 
来源:CSDN 
原文:https://blog.csdn.net/td_sexandzen/article/details/53785835 
版权声明:本文为博主原创文章,转载请附上博文链接!

关于linux fork() fcntl() 供使用linux fork vfork的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于fcntl 与 NFS、fcntl 函数用法 —— 操纵文件描述符状态、fcntl,lockf,哪个更适合用于文件锁定?、ioctl() fcntl() setsockopt() ioctlsocket() 用法的相关信息,请在本站寻找。

本文标签: