《unix环境高级编程》 读书笔记 (1)

近来读书,做些笔记,来年好翻翻。

本文所使用的操作系统为 CentOS7.0,如果不想装双系统的可以装虚拟机,可以参考这里:

http://blog.csdn.net/alex_my/article/details/38142229

当然啦,直接装个再好不过了。

File I/O


1 file descriptor

// 查看当前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文件,主要是用于调试。

RLIMIT_CPU: 设置每秒内的cpu Time,如果超过这个限制,则会发送SIGXCPU信号。

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错误。


2 lseek function

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

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


3 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


4 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,文件偏移量都会更新到文件末尾。


5 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指定位置。


6 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。


7 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_EXEC, 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)


8 ioctl function

ioctl 是设备驱动程序中对设备的IO通道进行管理的函数。

不同的设备驱动都会定义自己的ioctl指令。

后边讲到套接字的时候再具体详述。

再详细点的讲述可以看这里:

http://www.linuxidc.com/Linux/2007-12/9623.htm


参考:

http://blog.csdn.net/fatshaw/article/details/6294557

http://laokaddk.blog.51cto.com/368606/699563/

http://blog.csdn.net/zhangxinrun/article/details/7635570

http://www.ukuug.org/events/linux2001/papers/html/AArcangeli-o_direct.html

http://www.linuxidc.com/Linux/2007-12/9623.htm

时间: 2024-11-13 09:50:30

《unix环境高级编程》 读书笔记 (1)的相关文章

《Programming in Lua 3》读书笔记(二十二)

日期:2014.8.6 PartⅣ The C API 26 Extending Your Application 使用Lua很重要的一点是用来做配置语言.配合主语言做一些功能的配置. 26.1 The Basics 有的时候程序需要配置一些功能信息,很多时候可能有许多别的方法比用lua做配置要更简单:如使用环境变量或者读取文件,读取文件涉及到文件的解析.如果使用Lua进行配置的话,相当于用lua文件替代了要读取的如csv.txt文件等. 使用Lua进行配置的时候,就需要使用Lua API去控制

《Programming in Lua 3》读书笔记(二十一)

日期:2014.8.1 PartⅣ The C API 25 An Overview of the C API Lua是一种嵌入式语言.这就意味着Lua不是单独存在的,而是可以通过一系列的标准库将lua的特性嵌入至其他应用模块中. Lua以Lua interpreter(lua的解释器?)来解决了其不是独立程序,我们直到现在却又能独立使用Lua的问题.这个解释器是一个小型的程序(不超过500行代码),使用lua的标准库来实现独立解释程序,这个程序将处理与用户的交互等操作交给lua的标准库,这些库

读书笔记:《重来REWORK》

读书笔记:<重来REWORK> <重来Rework--更为简单有效的商业思维>这本书是看了别人的书单而购买的,初 拿到这本书翻看时,感觉有两点与平常的书不同,一是每个小节非常短,通常是一页,最多二页,二是附有大量的插图,原以为这些插图可能是用来凑页数的,但细 看一些插图,虽然都是用手工画的,但却能用形象的办法表示出一小节的观点,很象是出自做软件原型的人员之手. 这本书包含了80多个观点,特别适合指导小型软件公司的创业,感觉对我做的软件项目也有帮助. 卸负篇TAKEDOWNS 忘了“

【游戏设计模式】之四 《游戏编程模式》读书笔记:全书内容梗概总结

本系列文章由@浅墨_毛星云 出品,转载请注明出处.   文章链接:http://blog.csdn.net/poem_qianmo/article/details/53240330 作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442 本文的Github版本:QianMo/Reading-Notes/<游戏编程模式>读书笔记 这是一篇超过万字读书笔记,总结了<游戏编程模式>一书中所有章节与内容的知识梗概. 我们知道,游戏行业其实一直很缺一本系

读书笔记-2015年第1本:《暗时间》

作者所说的暗时间,其实在生活中,我自己也有领悟到,领悟的时候很感慨,然而过不了几天就把这个领悟给忘得一干二净,于是又是过着重蹈覆辙的生活.现在给我的提醒就是把领悟到的东西记录下来,每天空出一些时间静下心专门来思考这些领悟到的东西.现在有幸看到自己曾经遗忘的宝贵的生活哲理,好好思考,好好领悟. 在这本书中,作者推荐了大量有价值的学习资料以及学习方法,有时间时都可以去研究学习. 我们可以看出,作者很有学问,但也可以想一下为何如此有学问?“看上去好像很高端的样子”,实际上,也就是作者曾经在一年内看过很

【python下使用OpenCV实现计算机视觉读书笔记3】读写视频文件

Lua可以调用C函数的能力将极大的提高Lua的可扩展性和可用性. 对于有些和操作系统相关的功能,或者是对效率要求较高的模块,我们完全可以通过C函数来实现,之后再通过Lua调用指定的C函数. 对于那些可被Lua调用的C函数而言,其接口必须遵循Lua要求的形式,即typedef int (*lua_CFunction)(lua_State* L). 简单说明一下,该函数类型仅仅包含一个表示Lua环境的指针作为其唯一的参数,实现者可以通过该指针进一步获取Lua代码中实际传入的参数.返回值是整型,表示该

《程序员的呐喊》读书笔记(下)

接着<程序员的呐喊>读书笔记(上),继续分享下篇,这次干货比较多哦,有静动态类型的优缺点.强弱类型系统的对抗.设计模式.程序员的数学.编译器的重要性以及保守派自由派的较量,一时消化不了的建议保存以便read it later. 静态类型和动态类型的优缺点 静态类型的优点下面列出了静态类型的主要优点:(1)静态类型可以在程序运行之前,依赖其与生俱来的限制来及早发现一些类型错误.(或是在插入/更新记录,解析XML文档等情况下进行检测.)(2)静态类型有更多机会(或者说更容易)优化性能.例如只要数据

代码的未来读书笔记&lt;二&gt;

代码的未来读书笔记<二> 3.1语言的设计 对Ruby JavaScript Java Go 从服务端客户端以及静态动态这2个角度进行了对比. 这四种语言由于不同的设计方针,产生了不同的设计风格. Header 客户端 服务端 动态 Html5 Ruby 静态 Java Go 静态动态 静态:无需实际运行,仅根据程序代码就能确定结果. 动态:只有到了运行时才能确定结果.不过无论任何程序,或多或少都包含的动态的特性. 动态运行模式 运行中的程序能识别自身,并对自身进行操作.对程序自身进行操作的编

读书笔记:技术的本质-技术是什么,它是如何进化的 (布莱恩?阿瑟)

读书笔记算不算原创? - page 30 然而,作为人类,我们实际上不应该和技术如此紧密地结合,而是应该和其他什么东西融合得更为紧密,那就是自然.在最深的层次上,人的存在应该和自然,和我们最初的环境,以及最初使我们成为人的那些条件相融合. ========== - page 36 如今机器被用来生产机器了,同时它又变成了以后同类机器的父母. ========== - page 43 技术的建构不仅来自已有技术的组合,还来自于对自然现象的捕捉和征服.在 ========== - page 44 技

读书笔记:技术的本质-技术是什么,它是怎样进化的 (布莱恩?阿瑟)

读书笔记算不算原创? - page 30 然而.作为人类,我们实际上不应该和技术如此紧密地结合,而是应该和其它什么东西融合得更为紧密,那就是自然. 在最深的层次上.人的存在应该和自然,和我们最初的环境,以及最初使我们成为人的那些条件相融合. ========== - page 36 现在机器被用来生产机器了,同一时候它又变成了以后同类机器的父母. ========== - page 43 技术的建构不仅来自已有技术的组合.还来自于对自然现象的捕捉和征服.在 ========== - page 4