`
tomotoboy
  • 浏览: 162502 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

文件共享

阅读更多
UNIX支持在不同进程间共享打开文件,本文主要对以下几个方面简单介绍:
  • 原子操作;
  • 再次介绍dup与dup2;
  • fcntl函数;
  • ioctl函数;
  • /dev/fd;

1.介绍一下内核用于所有I/O的数据结构
内核使用了三种数据结构,它们之间的关系决定了在文件共享方面一个进程对另一个进程可能产生的影响。
(1) 每个进程在进程表中都有一个记录项,每个记录项中有一张打开文件描述符表,可将其视为一个矢量,每个描述符占用一项。与每个文件描述符相关联的是:
(a) 文件描述符标志。
(b) 指向一个文件表项的指针。


(2) 内核为所有打开文件维持一张文件表。每个文件表项包含:
(a) 文件状态标志(读、写、增写、同步、非阻塞等)。
(b) 当前文件位移量。
(c) 指向该文件v节点表项的指针。


(3) 每个打开文件(或设备)都有一个 v节点结构。
v节点包含了文件类型和对此文件进行各种操作的函数的指针信息。对于大多数文件, v节点还包含了该文件的 i节点(索引节点) 。这些信息是在打开文件时从盘上读入内存的,所以所有关于文件的信息都是快速可供使用的。例如, i节点包含了文件的所有者、文件长度、文件所在的设备、指向文件在盘上所使用的实际数据块的指针等等。

图1显示了进程的三张表之间的关系。该进程有两个不同的打开文件——一个文件打开为标准输入(文件描述符0) ,另一个打开为标准输出(文件描述符为1) 。

图1:打开文件的内核数据结构


如果两个独立进程各自打开了同一文件,则有图2中所示的安排:

图2:两个独立进程各自打开同一个文件

我们假定第一个进程使该文件在文件描述符 3上打开,而另一个进程则使此文件在文件描述符 4上打开。打开此文件的每个进程都得到一个文件表项,但对一个给定的文件只有一个 v节点表项。每个进程都有自己的文件表项的一个理由是:这种安排使每个进程都有它自己的对该文件的当前位移量。

2.原子操作
所谓原子操作,就是该操作绝不会在执行完毕前被任何其他任务或事件打断,也就说,它的最小的执行单位,不可能有比它更小的执行单位,因此这里的原子实际是使用了物理学里的物质微粒的概念。
单处理器中,在多进程(线程)访问资源时,能够确保所有其他的进程(线程)都不在同一时间内访问相同的资源。

3.dup与dup2
#include <unistd.h>
int dup(int filedes);
int dup2(int filedes, int filedes2);
两函数的返回:若成功为新的文件描述符,若出错为- 1

由dup返回的新文件描述符一定是当前可用文件描述符中的最小数值。用dup2则可以用filedes2参数指定新描述符的数值。如果filedes2已经打开,则先将其关闭。如若filedes等于filedes2,则dup2返回filedes2,而不关闭它。这些函数返回的新文件描述符与参数filedes共享同一个文件表项。

每个文件描述符都有它自己的一套文件描述符标志。正如我们将在下一节中说明的那样,新描述符的执行时关闭( close-on-exec )文件描述符标志总是由dup函数清除。复制一个描述符的另一种方法是使用 fcntl函数,下一节将对该函数进行说明。实际上,
调用:
dup (filedes ) ;
等效于:
fcntl (filedes, F_DUPFD, 0);
而调用:
dup2(filedes, filedes2) ;

等效于:
close(filedes2) ;
fcntl(filedes, F_DUPFD, filedes2);
在最后一种情况下,dup2并不完全等同于close加上fcntl。它们之间的区别是:
(1) dup2是一个原子操作,而close及fcntl则包括两个函数调用。有可能在close和fcntl之间插入执行信号捕获函数,它可能修改文件描述符。
(2) 在dup2和fcntl之间有某些不同的errno。


4.fcntl函数
fcntl函数可以改变已经打开文件的性质。
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
int fcntl(int filedes, int cmd ,…/*int arg*/ );
返回:若成功则依赖于cmd(见下),若出错为-1
在《unix环境高级编程》中提到:一般第三个参数是一个整数,与上面所示函数原型中的注释部分相对应。但是在书中提到在说明记录锁时,第三个参数则是指向一个结构的指针。
fcntl函数有五种功能:
  • 复制一个现存的描述符(cmd=F_DUPFD)
  • 获得/设置文件描述符标记(cmd=F_GETFD或F_SETFD)
  • 获得/设置文件状态标志(cmd=F_GETFL或F_SETFL)
  • 获得/设置异步I/O有权(cmd=F_GETOWN或F_SETOWN)
  • 获得/设置记录锁(cmd=F_GETLK , F_SETLK或F_SETLKW)

  • F_DUPFD 复制文件描述符filedes, 新文件描述符作为函数值返回。它是尚未打开的各描述符中大于或等于第三个参数值(取为整型值)中各值的最小值。新描述符与 filedes 共享同一文件表项 。但是,新描述符有它自己的一套文件描述符标志,其 FD_CLOEXEC文件描述符标志则被清除。
  • F_GETFD   对应于filedes 的文件描述符标志作为函数值返回。当前只定义了一个文件描述符标志FD_CLOEXEC。
  • F_SETFD   对于filedes 设置文件描述符标志。新标志值按第三个参数(取为整型值)设置。
  • 应当了解很多现存的涉及文件描述符标志的程序并不使用常数 FD_CLOEXEC,而是将此标志设置为0 (系统默认,在exec时不关闭)或1 (在exec时关闭)。
  • F_GETFL   对应于filedes 的文件状态标志作为函数值返回。在说明open函数时,已说明了文件状态标志,如图3所示:

图3:对于fcntl的文件状态标志

不幸的是,三个存取方式标志( O_RDONLY, O_WRONLY,以及O_RDWR )并不各占1位。(正如前述,这三种标志的值各是 0、1和2,由于历史原因。这三种值互斥—一个文件只能有这三种值之一。)因此首先必须用屏蔽字O_ACCMODE取得存取方式位,然后将结果与这三种值相比较。[list]
  • F_SETFL   将文件状态标志设置为第三个参数的值(取为整型值)。 可以更改的几个标志是:O_APPEND,O_NONBLO CK,O_SYNC和O_ASYNC。
  • F_GETOWN   取当前接收SIGIO和SIGURG信号的进程I D或进程组ID。
  • F_SETOWN   设置接收SIGIO和SIGURG信号的进程ID或进程组ID。正的arg指定一个进程ID,负的arg表示等于arg绝对值的一个进程组 D。
  • [/list]fcntl的返回值与命令有关。如果出错,所有命令都返回-1,如果成功则返回某个其他值。下列三个命令有特定返回值:F_DUPFD,F_GETFD, F_GETFL以及F_GETOWN。第一个返回新的文件描述符,第二个返回相应标志,最后一个返回一个正的进程I D或负的进程组ID。
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <fcntl.h>
    int main(int argc, char *argv[])
    {
       int accmode, val;
       if(argc !=2){
         printf("usage:  pro_2 <descriptor#>");
         exit(1);
        }
       if((val=fcntl(atoi(argv[1]),F_GETFL,0))<0)
        {
            printf("fcntl error for fd %d",atoi(argv[1]));
            exit(1);
       }
        accmode=val&O_ACCMODE;
        if(accmode==O_RDONLY) printf("read only");
        else if(accmode==O_WRONLY) printf("write only");
        else if(accmode==O_RDWR) printf("read write");
        else{
            printf("unknown access mode");
            exit(1);
         }
          if(val & O_APPEND) printf(", append");
          if(val & O_NONBLOCK) printf(", nonblocking");
       #if !defined(_POSIX_SOURCE)&&defined(O_SYNC)
           if(val&O_SYNC) printf(", synchronous writes");
       #endif
          putchar('\n');
          exit(0);
    
    }

    /home/l/g/tomotoboy/io >gcc pro_2.c -o pro_2
    /home/l/g/tomotoboy/io >pro_2 0 </dev/tty
    read only
    /home/l/g/tomotoboy/io >pro_2 2 2>temp.foo
    write only
    /home/l/g/tomotoboy/io >pro_2 2 2>>temp.foo
    write only, append


    一个对于一个文件描述符设置一个或多个文件状态标志的函数
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <fcntl.h>
    void set_fl(int fd, int flags) /* flags are file status flags to turn on*/
    {
    	int val;
    	if((val = fcntl(fd, F_GETFL ,0))<0){
    		printf("fcntl FGETFL error");
    		exit(1);
                    }
    	val |=flags; /* turn on flags */
     	if(fcntl(fd, F_SETFL ,val)<0){
    		printf("fcntl F_SETFL error");
    		exit(1);
    	}
    }

    如果将中间的一条语句改为:
    val &= ˜flags;        /*turn flags off*/

    就构成了另一个函数,我们称其为 clr_ fl,并将在后面某个例子中用到它。此语句使当前文件状态标志值val与flags的反码逻辑与运算。如果在程序pro_3的开始处,加上下面一行以调用set_fl,则打开了同步写标志。
    set_fl(STDOUT_FILENO, O_SYNC);

    这就造成每次write都要等待,直至数据已写到磁盘上再返回。

    5.ioctl函数


    6./dev/fd
    比较新的系统都提供名为/dev/fd的目录,其目录项是名为 0、1、2等的文件。打开文件/dev/fd /n等效于复制描述符n (假定描述符n是打开的)。




    参考质料
    《UNIX环境高级编程》
    百度百科-原子操作
    Linux原子操作
    • 大小: 19.3 KB
    • 大小: 22.3 KB
    • 大小: 11.8 KB
    分享到:
    评论

    相关推荐

      WIN 10因为文件共享不安全,所以你不能连接到文件共享.docx

      在使用Windows10系统访问共享文件的时候,提示因为文件共享不安全,不能连接到文件共享,这是怎么回事呢?如何才能够连接到文件共享呢?下面来看一下设置方法吧。 工具/原料 Windows10 方法/步骤 1.在Windows10...

      大势至局域网文件共享管理系统 v10.5

      大势至局域网文件共享管理系统可以详细审计局域网电脑访问服务器共享文件的行为,包括新建、拷贝、修改、删除、剪切、重命名等操作,从而便于对员工访问共享文件的行为进行全程的记录和查证,便于网管员进行事后审计...

      linux文件共享服务汇总

      1、samba服务器 Windows与Linux文件共享 (主局域网) 1.1samba服务器介绍 1.2samba服务的启动和进程 1.3Samba 配置 1.4samba服务器端常用命令 1.5Samba应用示例一:linux用户在window端访问宿主目录 1.6Samba应用...

      php实现文件共享(其于windows网上邻居原理)

      php实现文件共享(其于windows网上邻居原理)  通过本php文件,在进行相关设置后,您可以方便的看到共享目录中的文件,以及相应的说明,便于能够迅速找到自己想要的文件。  找到想要的东西后,直接点击文件夹名打开...

      实现Windows与VMware下Linux的文件共享

      实现Windows与VMware下Linux的文件共享实现Windows与VMware下Linux的文件共享实现Windows与VMware下Linux的文件共享实现Windows与VMware下Linux的文件共享

      HTTP文件共享软件

      WINDOWS平台下的桌面程序,用来快速共享文件,搭建文件共享服务器

      Windows2016文件共享设置配额

      Windows2016文件共享设置配额(限制共享文件夹能写入的大小)

      NFS文件共享.docx

      NFS 文件共享服务,NFS(NetworkFileSystem)网络文件系统,是一种基于 TCP/IP 传输的网络文件系统协议, 最初由 SUM 公司开发。通过使用 NFS 协议,客户机可以向访问本地目录一样访问远程服务 器中的共享资源。 NFS...

      python大作业基于django实现的轻量级文件共享系统源码.zip

      python大作业基于django实现的轻量级文件共享系统源码 实现的功能: 文件共享(上传、下载) 文件搜索(目前仅支持全文搜索) 用户文件管理(目前仅支持用户文件查看)等等等等 python大作业基于django实现的轻量级...

      http文件共享服务器v1.0

      该程序是一个免费的、HTTP协议的文件共享服务器,使用浏览器可以...与其他常用文件共享方式(如FTP,飞秋,网盘,自己建站)相比,具有使用简单,适用场景更多的优点,在个人使用以及共享给他人的场景中非常方便快捷。

      虚拟机LINUX与主机WINDOWS文件共享

      虚拟机LINUX与主机WINDOWS文件共享

      http文件共享服务器 v1.4

      该程序是一个免费的、HTTP协议的文件共享...支持快速分享文字片段 与其他常用文件共享方式(如FTP,飞秋,网盘,自己建站)相比,具有使用简单,适用场景更多的优点,在个人使用以及共享给他人的场景中非常方便快捷。

      在VMware的ubuntu虚拟机中实现和Windows文件共享

      本文图文并茂的描述了如何在VMware的ubuntu虚拟机中实现和Windows文件共享。

      Python 实现局域网内文件共享功能

      Python 实现局域网内文件共享功能,使用 Python 的 sockets 模块实现的方法。分为客户端和服务器。代码简单。python大作业

      jsp办公室文件共享系统

      该办公室文件共享系统,采用了BS架构模式开发,实现了办公室的文件共享功能。

      p2p文件共享程序

      p2p文件共享程序 java课程设计 java设计。。。。。。。。。

      HTTP文件共享器hfs

      HTTP文件共享器 可共享文件!!!!!!!!!!!!!!

      ftp文件共享服务器

      超经典ftp文件共享服务器,文件超小,很好用的

      怎么实现文件共享

      实现计算机之间的文件共享,主机之间能够互相访问各自的文件。快捷准确的配置主机与共享主机之间的设置。

      虚拟机文件共享 设置详细步骤

      虚拟机文件共享 设置详细步骤 虚拟机文件共享 设置详细步骤 虚拟机文件共享 设置详细步骤

    Global site tag (gtag.js) - Google Analytics