Linux系统文件,资源相关总结

文件
  • 描述符
    // 查看当前session中的fd数量限制
    ulimit -n

// 修改当前session中的fd数量限制
ulimit -n your_need

可以在一个终端使用以上命令,另外再打开一个进行查看。
使用实例:
在这里插入图片描述

在程序中,可以使用系统函数进行修改
#include <sys/resource.h>
struct rlimit
{
rlim_t rlim_cur;
rlim_t rlim_max;
}
int getrlimit(int resource, struct rlimit* rlim);
int setrlimit(int resource, const struct rlimit* rlim);
// ext:

  • 资源(resource)可选择的有:

RLIMIT_CORE: 设置core文件的大小,0表示禁止创建core文件。一个程序崩溃的时候,会在指定目录生成一个core文件,主要是用于调试。
(core文件:仅仅是内存的一个映像,加上调试信息,插产生core文件是大多数UNIX系统的实现功能: core译: 核心,要点)
RLIMIT_CPU: 设置每秒内的cpu Time,如果超过这个限制,则会发送SIGXCPU信号。
(如果进程超过其软CPU时间限制,则产生SIGXCPU信号: SIGXCPU:默认动作说明为“终止或终止core”)

RLIMIT_DATA: 设置进程中data segment大小,单位为bytes。如果超过这个限制,malloc()会失败。具体关于data segment 参考这里: http://blog.csdn.net/fatshaw/article/details/6294557

RLIMIT_FSIZE: 设置进程内文件最大长度,如果超过这个长度,则产生SIGXFSZ信号。
如果线程阻塞,或者进程抓取或者忽略了这个信号,则会从底部减少文件大小并设置EFBIG错误。

RLIMIT_NOFILE: 设置文件描述符大小,比最大文件描述符大一,如果超过了这个限制,则申请文件描述符失败,并且设置EMFILE错误。

RLIMIT_STACK: 设置进程最大堆栈,单位为bytes。

RLIMIT_AS: 设置进程可用内存,单位为bytes。如果超过这个限制,malloc()和mmap()将会失败,并设置ENOMEM错误。

  • lseek function

off_t lseek(int fildes, off_t offset, int whence) 移动读/写偏移量 (offset: 偏移量)

whence可选择的有:
SEEK_SET: 文件偏移量设置为 offset
SEEK_CUR: 文件偏移量设置为 当前偏移量 + offset
SEEK_END: 文件偏移量设置为 文件大小 + offset

获取当前偏移量的方法:

offset value = lseek(fd, 0, SEEK_CUR);

当操作的文件为 pipe, FIFO, socket时,返回-1,并设置错误为ESPIPE。

其它错误可以man 3 lseek查阅.

程序用例:test2.1.cc

#include <stdio.h>
#include <unistd.h>

int main(int argc, char** argv)
{
     if(lseek(STDIN_FILENO, 0, SEEK_CUR) == -1)
          printf("Seek Failed\n");
     else
          printf("Seek OK\n");

     return 0;
}

g++ -o test2.1 test2.1.cc
./test2.1
输出:Seek Failed。原因:参数1 fildes必须是已经打开的文件描述符.
./test2.1 < /etc/passwd
输出:Seek OK
另外,关于main函数列表上的两个参数,可以这么记:
int main(int arg-count, char** arg-variable);
第一个是参数数量,第二个是参数变量集合

  • 文件资源(File Sharing – close-on-exec)

当使用fork创建子线程后,子线程获得父进程的数据空间,堆和栈的副本,也包含文件描述符,共享共同的打开文件标记,当前的偏移量等。

当在子进程中调用exec执行另一个程序时,替换了当前进程的正文,数据,堆和栈,即原先的子进程中的文件描述符丢失了(并未关闭),无法再关闭这些在子进程中不再使用到的文件描述符。而文件描述符是系统珍贵资源,数量有限。

一种办法是在执行exec之前先把这些文件描述符关闭,但在复杂的系统中,这是一件比较麻烦的事情。

另一种办法是打开文件的时候就指定好,当子进程执行exec的时候,这个文件关闭。即所谓的close-on-exec。

// 通过fcntl实现
int flags = fcntl(fd, F_GETFD);
flags |= FD_CLOEXEC;
fcntl(fd, F_SETFD, flags);

// 在创建或打开文件的时候指定
int fd = open(“text.log”, O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC);

具体查看man 2 open或者man 2 creat

  • Atomic Operations – O_APPEND

有这样一个例子:

程序A和程序B对同一个文件进行写操作。
程序A先写入1500字节,程序B打开,调用lseek,得到文件末尾为1500, 写入100字节。
程序A执行,此时,程序A的file table entry记录文件末尾为1500,写入100字节。此时,覆盖了程序B写入的内容。

解决方案:

// 每次write的时候,都调用lseek,获取文件末尾偏移量。

// 在创建或者打开的时候设置参数O_APPEND, 设置此标记后,每次调用write,文件偏移量都会更新到文件末尾。

  • open a file

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

flags可以选择的值:
必选其一:O_RDONLY, O_WRONLY, O_RDWR
可选:
O_CLOEXEC : 查看本文 “3 File Sharing – close-on-exec”
O_CREAT : 如果文件不存在,则创建
O_DIRECT : 直接进行文件IO,系统尽量不进行缓存。具体可参考以下链接,查看本文"8 fcntl function"中的
内容。
O_DIRECTORY : 如果path所指文件并非是一个目录,则会打开失败
O_EXCL : 如果O_CREAT和O_EXCL同时设置,如果文件不存在,则会创建文件,如果存在,则会打开失败。
如果O_CREAT和O_EXCL同时设置,且欲打开的文件为符号连接,则会打开失败。
O_NOCTTY : 如果欲打开的文件为终端机设备,则不会将该终端机当成进程控制终端机。
O_NOFOLLOW : 如果path所指文件是一个符号链接,则会打开失败
O_TRUNC : 如果文件存在且以可写方式打开时,会令文件长度为0,且数据会丢失。
O_TTY_INIT : 恢复终端默认属性。
O_APPEND : 读写文件会从文件末尾开始。
O_SYNC : 同步方式,任何写操作会阻塞进程直到写入到底层硬件中。
O_ASYNC :
O_LARGEFILE : 用于打开超大文件,具体说明需另外查找。
O_NOATIME : 读文件不更新最后访问时间。
O_NONBLOCK : 非阻塞方式
O_PATH :

mode在创建新文件的时候启作用,设置文件属性。
mode可以选择的值:
位于读书笔记(2)中的第五点:“5 改变文件的操作权限”

程序示例:
// test2.2.cc


#include <stdio.h>
#include <fcntl.h>
#include <errno.h>

int main(int argc, char* argv[])
{
     // 以读写的形式打开一个文件,如果不存在,则创建     
     int fd = ("test2.2.logc", O_RDWR | O_CREAT);
     if(fd == -1)
          printf("file open failed, error[%d].\n", errno);
     else
          printf("file open success, fd[%d].\n", fd);

     return 0;
}

  • creat and close a file

#include <fcntl.h>
int creat(const char *pathname, mode_t mode);

mode可选值如果open中的mode可选值,同样参考:
位于读书笔记(2)中的第五点:“5 改变文件的操作权限”

操作creat相同于如下语句:

open(pathname, O_RDWR | O_CREAT | O_TRUNC, mode);

注意的是,调用creat是以只写方式打开所创建的文件,如果要读文件,必须先close,然后open.

或者使用上述形式的open函数打开一个文件。

#include <unistd.h>
int close(int fd);

当一个进程终止时,内核自动关闭它所有打开的文件。

  • Atomic Operations – pthread, pwrite

对一个文件指定位置进行写入或者读取,有两个步骤:

-1: 调用lseek,设置偏移量
-2: 调用read或者write操作。

两步操作在过程中可能被打断,得到的不是需要的结果。

而pthread/pwrite可以解决这个问题:

ssize_t pread(int fd, void *buf, size_t count, off_t offset);

ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);

使用pthread/pwrite并不会改变当前文件偏移量。

当打开文件时指定了参数O_APPEND时,pwrite总是添加到文件末尾,而不会按照参数offset指定位置。

  • dup, dup2, dup3

int dup(int oldfd);
int dup2(int oldfd, int newfd);
int dup3(int oldfd, int newfd, int flags);

这些系统调用将会创建一个文件描述符的副本。

dup将返回一个未使用的最小的文件描述符

dup2将返回一个指定的文件描述符。如果oldfd指定了文件描述标记(close-on-exec),newfd并不会拥有。
需要重新使用fcntl指定。

如果newfd已经存在,则会先被关闭。
如果oldfd和newfd数值相同,且oldfd是有效的文件描述符,则dup2不做任何事情,返回newfd。
如果oldfd和newfd数值相同,且oldfd是无效的文件描述符,则调用失败, 不会调用newfd关闭的步骤。

dup3效果与dup2相同,但可以通过指定flags为O_CLOEXEC,使得newfd具有close-on-exec功能。

如果oldfd和newfd数值相同,则调用失败,并设置错误为INVAL。

  • fcntl function

#include <unistd.h>
#include <fcntl.h>

int fcntl(int fd, int cmd, … /* arg */ );

可以改变一个已经打开的文件的属性

其中, cmd 可选择的有:

F_DUPFD: 返回一个大于等于参数3且最小未使用的文件描述符,与fd共享一个文件表项,如果fd有文件描述符标志(目前只有一个,FD_CLOEXEC),则此标志会被清除。可以查看dup2相关。
F_DUPFD_CLOEXEC: (since Linux 2.6.24) 效果等同于F_DUPFD,但会给返回的文件描述符添加close-on-exce标志。
F_GETFD: 返回fd的文件描述符标志。目前仅有一个标志:FD_CLOEXEC
F_SETFD: 将参数3设置为fd的文件描述符标志。
F_GETFL: 返回fd的文件状态标志,即open时候的flags标记。

           O_RDONLY, O_WDONLY, O_RDWR, O_EXCL, O_SEARCH, 
           O_APPEND, O_NONBLOCK, O_SYNC, O_DSYNC, O_RSYNC, O_FSYNC, O_ASYNC

F_SETFL: 设置fd的文件状态标志,可设置的值有(Linux下, 本机为CentOS7.0, Mac和FreeBSD有不同的选项):

           O_APPEND, 每次write的时候都将添加到文件的末尾,效果等同于open的时候添加O_APPEND标记。

           O_NONBLOCK, 非阻塞IO,如果read没有数据可读,或者write操作阻塞,则返回-1并且设置错误为 
                     EAGAIN。
       
           O_ASYNC, 当IO可用时,允许发送SIGIO信号到进程组。

           O_DIRECT, 直接进行文件IO,系统尽量不进行缓存。具体可参考以下链接:

http://blog.csdn.net/zhangxinrun/article/details/7635570
http://laokaddk.blog.51cto.com/368606/699563/
http://www.ukuug.org/events/linux2001/papers/html/AArcangeli-o_direct.html

           O_NOATIME, 读文件不改变最后访问时间。

另外还有F_GETOWN, F_SETOWN, F_GETOWN_EX等等,具体查看fcntl(2)

  • ioctl function

ioctl 是设备驱动程序中对设备的IO通道进行管理的函数。
不同的设备驱动都会定义自己的ioctl指令。
后边讲到套接字的时候再具体详述。

再详细点的讲述可以看这里:
http://www.linuxidc.com/Linux/2007-12/9623.htm

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值