linux 编程学习笔记
文章平均质量分 88
--Allen--
我知道我不知道。
展开
-
1-gcc 选项
gcc 常用选项 -v :查看gcc版本号 -I:注意这是大写的 i,指定头文件目录,注意-I和目录之间没有空格 -c :只编译,生成.o文件,不进行链接 -g :包含调试信息 -On :n=0∼3 编译优化,n越大优化得越多 -Wall :提示更多警告信息 -D :编译时定义宏,注意-D和之间没有空格 -E :生成预处理文件 -M :生成.c文原创 2016-09-15 14:53:56 · 4759 阅读 · 0 评论 -
2-静态库的创建与使用
生成静态库的指令 ar示例一个完整的生成 a 文件的例子编写源码生成 o 文件打包使用静态库客户端测试代码编译链接成最终的可执行文件生成静态库的指令 ar常用选项 选 项 说 明 d 从归档文件中删除文件 m[ab] 在归档文件中移动文件 p 打印在归档文件中找到的文件 q[f] 将文件快速追加到归档文件中 r[ab][f][u] 替换归原创 2016-09-15 16:29:53 · 4626 阅读 · 9 评论 -
3-共享库的创建与应用
要用到的文件生成动态库的命令使用动态库-fpic 选项要用到的文件文件树如下 . |-bin |-lib |-src |-add.c |-common.h |-main.c |-sub.c// 文件名:common.hint add(int a, int b);int sub(int a, int b);// 文件名:add.cint add原创 2016-09-15 19:44:26 · 3247 阅读 · 1 评论 -
5-文件IO-read/write/open
代码函数 openopen 函数的用法flag 选项示例函数 read函数 write完整代码小结本着在使用中学习的原则,现在提出一个需求,只使用 linux 系统接口来实现文件拷贝命令。在上一篇博文中,已经简单了解了库函数和系统接口的区别。本文将继续学习 write,另外还将学习另外两个系统接口 read 和 open.代码为了方便学习,我把所有的错误处理的代码删除了。如果你想看完整原创 2016-09-17 15:17:06 · 4171 阅读 · 3 评论 -
9-文件系统初探
有不少初学者对文件系统这个概念比较茫然,不知道文件系统是干嘛的。什么 FAT, NTFS, ext2, ext3 等等搞的初学者晕头转向。而教材上讲解的文件系统又过于抽象和理论化,不利于初学者。文件系统为何物不妨先来看看百度百科给出的定义: 文件系统是操作系统用于明确存储设备或分区上的文件的方法和数据结构;即在存储设备上组织文件的方法。有些初学者恨不得一板砖拍到写这条定义的人脸上。当然这也不能原创 2016-10-08 17:08:02 · 2463 阅读 · 4 评论 -
7-文件IO-阻塞与非阻塞IO
1. 阻塞 IO通常来说,从普通文件读数据,无论你是采用 fscanf,fgets 也好,read 也好,一定会在有限的时间内返回。但是如果你从设备,比如终端(标准输入设备)读数据,只要没有遇到换行符(‘\n’),read 一定会“堵”在那而不返回。还有比如从网络读数据,如果网络一直没有数据到来,read 函数也会一直堵在那而不返回。read 的这种行为,称之为 block,一旦发生 bl...原创 2016-09-25 19:01:51 · 5926 阅读 · 5 评论 -
8-文件IO-fcntl函数
回忆文件表还记得在第7篇文章提到过,阻塞与非阻塞是文件本身的属性吗?再回想一下,第6篇《文件IO-lseek》中提到的一些内核数据结构,每个描述符是某个数组的一个索引,这个数组每个元素保存了一个指向文件表的指针。这个文件表的结构如下。struct file { unsigned short f_mode; // 文件权限位 unsigned short f_flags; // 文件状原创 2016-09-25 21:24:02 · 2391 阅读 · 4 评论 -
14-stat 结构体中的三个时间
stat 结构体中有三个 time_t 类型的字段,分别是 st_atime,st_mtime,st_ctime.1 三个时间的含义1.1 st_atime文件最后一次被访问的时间。调用 creat(), mknod(), pipe(), utime(), and read()这些函数会改变 st_atime 的值。1.2 st_mtime文件内容最后一次被修改的时间。调用 creat(), mkn原创 2016-11-28 20:55:10 · 4436 阅读 · 1 评论 -
15-linux 中的时间
上一篇的一个遗留问题,是有关时间的可读性问题,毕竟用整数来表示时间太不直观。linux 有关时间的类型和函数在 time.h 这个头文件中。接下来,我们主要介绍两个与时间相关的类型(time_t 和 struct tm)以及三个函数(gmtime 、 localtime 和 mktime).知识点:两个类型 time_tstruct tm三个函数 gmtimelocaltimemkti原创 2016-11-30 14:23:16 · 1579 阅读 · 0 评论 -
12-stat 函数
在 linux 中,经常需要获取文件的属性,比如修改时间,文件大小等等。stat 函数将会帮助我们得到这些信息。原创 2016-11-28 10:50:30 · 2729 阅读 · 4 评论 -
17-chown 函数
如果你对 linux 中的命令 chown比较熟悉的话,学起 chown 函数也会格外轻松。chown 命令只能工作在 root 权限下,主要用来修改文件的所有者和所属组。1 chown 命令下面以实例简单讲解下 chown 的使用方法。当前登录的账号是 allen.创建测试文件$ touch test.txt$ ls -l test.txt-rw-rw-r-- 1 allen allen原创 2016-12-01 16:55:19 · 2020 阅读 · 0 评论 -
18-utime 函数
utime 函数可以用来更改文件的最近访问时间和最近修改时间,即 atime 和 mtime。如果你不知道这两个时间是什么含义,请参考《stat 结构体中的三个时间》 。1 utime 函数原型/*struct utimbuf { time_t actime; // access time time_t modtime; // modification tim原创 2016-12-01 17:44:07 · 2075 阅读 · 2 评论 -
19-文件截断与 truncate 函数
所谓的截断,就是把一个文件的尾部砍掉。truncate 函数可以非常容易的做到这一点。它的原型如下:int truncate(const char *path, off_t length);1 truncate 函数示例下面给一个简单的示例来说明。这段代码的功能是将指定文件截断成固定长度。代码// 文件名: mytruncate.c#include <unistd.h>#include <s原创 2016-12-01 18:31:17 · 4438 阅读 · 0 评论 -
21-link系列的函数
link 系列的函数,主要是用来创建链接,删除链接的。主要有 link、symlink、unlink、readlink 这几个。它们的功能如下: 函数 功能 link 创建硬链接 symlink 创建软链接(符号链接) unlink 删除硬链接或软链接 readlink 读取软链接文件自身内容(不是所指向的文件内容)1 实例在此之前先创建测试文件 test.t原创 2016-12-02 14:51:14 · 1546 阅读 · 0 评论 -
22-与目录有关的函数-chdir 与 getcwd
chdir 这个命令类似于 linux 的命令 cd,而 getcwd 有点像 pwd。1 先入为主也许你自认为对 cd 命令和 pwd 命令相当熟悉了,那么,先看下面的例子。1.1 代码函数原型int chdir(const char *path);char *getcwd(char *buf, size_t size);实例这段代码的目的是实现一个类似 cd 的命令,同时打印 cd 后原创 2016-12-03 22:22:47 · 1467 阅读 · 0 评论 -
4-文件IO-从printf开始
本着从使用中学习原则,我不打算讲太多的细节,也不想讲太多有关内核的知识。但是适当的了解一点内核,对学习 linux 编程会非常有帮助。printf 在干什么学过C语言的朋友第一天学习的函数恐怕就是 printf("Hello world\n")了,无论是在 Windows下,还是 Linux 下,这个函数都能使用。对我们程序员来说,它的底层实现是透明的。而 printf ,就是所谓的 C 语言库函数原创 2016-09-17 11:36:49 · 3926 阅读 · 4 评论 -
23-与目录有关的函数-mkdir 与 rmdir
mkdir 是用来创建一个空目录的,而 rmdir 用来删除空目录。与 linux 命令的 mkdir不同的是,mkdir 函数需要指定目录的权限位。想必你已经对 mode 相当熟悉了。不过,对于目录来说,权限位还有一些坑,也没那么容易。1 目录的权限位目录的权限位,至少要设置一个执行许可位。即 rwx 中的那个 x 位。如果不设置,就没办法使用 cd 命令进入目录,也无法读取目录下的文件内容。所原创 2016-12-04 18:13:00 · 1395 阅读 · 0 评论 -
25-文件与目录总结
到这里,文件系统相关的知识基本上算告以段落。博客所讲述的远远只是文件与目录中的一部分,不可能面面俱到。这一篇将文件与目录相关的内容进行梳理,可以对照着看看,还有哪些知识点没搞清楚。其中重要的部分已经加粗,一定要重点掌握和理解。当然,其它知识点也是相当重要的。文件系统dir_entry 结构体inode 结构体stat 函数st_mode 字段的结构以及 chmod 函数chown 函数原创 2016-12-05 20:48:05 · 1112 阅读 · 0 评论 -
26-感受进程
当你编译完一段代码生成 a.out 后,在命令行键入 ./a.out,这时候,就有一个(或多个)新的进程产生了(前提你的 a.out 没问题^_^).在此之前,a.out 文件只是一份保存在你硬盘上的死物而已,它并不是进程。一旦你在你的终端里键入./a.out,你的终端 shell(它也是个进程,一个活物) 就会把 a.out 文件读到内存,一旦把控制权交给内存中的这段 a.out (称之为内存映像原创 2016-12-13 14:40:06 · 2374 阅读 · 0 评论 -
10-ext2 文件系统
上一篇简单介绍了一下什么是文件系统,最后我们尝试自己在一张A4纸上构造了一个属于我们自己的文件系统——happyfs。可惜的是,我们这个 happyfs 并不为世人所知,它的闻名程度远不及大名鼎鼎的 ext2。ext2 是早期 linux 上使用的文件系统,堪称经典也不复杂。从它入手,比较简单,也方便以后我们学习更复杂的文件系统。ext2 如何划分它的A4纸 图1 ext2全貌 看来 ext原创 2016-10-09 11:00:59 · 2653 阅读 · 0 评论 -
32-wait大变身之waitpid
上一篇,介绍了僵尸进程的概念,也学会了用 wait 清除它。实际上,wait 函数的本质并不是为清除僵尸进程而存在,而是为了获取子进程状态。只要子进程的状态发生了改变,它就会给父进程发信号。比如子进程暂停执行,会告诉父进程:爹,我暂停了(SIGSTOP),如果又恢复执行了,又会告诉父进程:爹,我恢复执行了(SIGCONT)。这些信号,父进程都可以忽略,没什么关系。只是当子进程给父进程发送正原创 2016-12-21 10:32:14 · 2224 阅读 · 4 评论 -
50-进程间通信总览
在上一篇里,使用了读写文件的方式来实现进程间通信,使用了信号量完成了进程间的同步,虽然这种实现方式也能够完成任务,但是缺点就在于它需要读写磁盘。所以 linux 系统提供了多种多样的进程间通信的手段,帮助我们实现进程间通信。不过,在讲解 Linux 进程间通信(后面简称 Linux IPC)之前,需要了解 Linux IPC的分类。1. Linux IPC 分类说分类不太准确,不过还是先按照此方式大原创 2017-01-03 17:48:15 · 1582 阅读 · 0 评论 -
33-Hello signal
进程初步已经结束,不过有关进程的知识点还有太多太多,有关进程的其它知识暂且往后挪。你也知道,你已经不止一次遇到信号这个陌生又熟悉的词语了。而且信号和进程,本来就是相互掺和在一起。所以,从这一篇开始,我们对信号说 hello.1. hello signal 程序如果你第一次学习 hello world 一样,这里写一个简单的 hello signal 程序。我的目的是希望借助 hello signal原创 2016-12-22 14:55:24 · 2000 阅读 · 0 评论 -
34-招待你的“客人”
对于进程来说,信号就像它的客人。客人来了,进程没好好执行它,那么客人会很生气,后果很严重。比如你发送信号 1 信号 2 给进程,直接导致进程退出。客人来你家了,如果你不理会,导致的就是你家被毁(^_^客人还是挺牛逼的)。本篇学习一个标准 C 库的函数 signal,这个函数,可以帮助我们执行指定的客人。1. 如何招待按照规则编写信号处理函数使用 signal 函数安装你刚刚编写的信号处理函数,同原创 2016-12-23 11:33:52 · 2169 阅读 · 2 评论 -
35-标准信号及其不可靠性
信号你会发了,也会捕了,但是还有好些个坑没填上。之前一直强调发送信号 1 - 31 号,实际上,还有 32-64 号信号。为什么不发 32-64 号信号,是因为32-64号和前面的 1- 31 号不属于一个范畴。1-31号,被规定为 standard signals,也就是标准信号。32-64号信号,被规定为 real-time signals,也就是实时信号。目前我们只关心标准信号,而不关心实时信原创 2016-12-23 17:30:10 · 2278 阅读 · 7 评论 -
27-fork 函数与分身术
初步体验进程的概念后,你也知道了你的 a.out 进程实际上是由终端 bash 进程创造出来的。那 bash 进程的父进程又是谁呢?如果你不断追溯下去,你就会发现,最终于那个进程就是 pid 为1 的 init 进程,而 init 进程,又是由一个 pid 为 0 的进程通过系统调用 fork 生成的,它也是第一个由 fork 函数创造出来的进程(linux 0.11 内核)。fork 是本篇的重点原创 2016-12-18 16:41:44 · 2647 阅读 · 1 评论 -
37-使用 kill 函数发送信号
一直以来,我们给程序发送信号都是通过快捷键(Ctrl+C, Ctrl+Z, Ctrl+\) 或者使用系统命令kill来向进程发送信号(还有一种是系统给你发送的信号,比如 SIGCHLD、SIGSEGV 等等)。除此之外,也可以通过函数 int kill(pid_t pid, int sig) 来向进程发送信号。kill 函数是 POSIX 定义的。实际上还有一个函数名为 raise,它是 ANSI原创 2016-12-24 13:31:38 · 3503 阅读 · 3 评论 -
38-启动定时炸弹 alarm
除了能够使用 kill 函数发信号,本篇再学习一个很重要的信号发送函数 alarm. 该函数不像 kill 函数可以给其它进程发送信号,它只能给自己发信号。另外,它只能发送 SIGALRM 信号。有同学会问,那要它何用?还不如用 kill 函数呢。其实,alarm 的强大之处在于它可以做到多少秒后发送消息——感觉像极了定时炸弹(不用担心,你的电脑不会爆炸)。1. alarm 函数unsigned i原创 2016-12-26 11:43:15 · 1759 阅读 · 0 评论 -
29-fork 函数与文件共享
不知道大家考虑过这样的问题没:如果进程在 fork 之前打开了一些文件,那么 fork 完之后,这些文件的描述符是共享的,还是不共享的?聪明的同学阅读了上篇《进程空间》的相关内容,脑子应该立即反应过来:父子进程的进程地址空间都是隔离的啊!所以打开的文件,应该也互不影响吧!No! No! No! 很抱歉,上一篇我的确讲过进程空间是隔离的。为了循序渐近和压缩篇幅,我不得不相关内容挪到此篇。进程 4GB原创 2016-12-19 16:07:30 · 2232 阅读 · 0 评论 -
39-装信号的容器 sigset
看到这个标题有同学会产生一些疑问(手动黑人问号),信号能被装进容器吗?答曰:能。为什么需要容器来装信号?其实还是方便 linux 内核处理信号,当然也方便用户程序处理。试想一下,如果同时发送了好多不同的信号给进程,然而进程一次只能处理一个信号,所以进程得把接收到的信号先保存起来才行。1. sigset_tPOSIX 定义一个数据结构 —— sigset_t ,从名称也可以看出这是通过 typedef原创 2016-12-26 14:40:36 · 2474 阅读 · 0 评论 -
30-换个姿势执行 ls 命令
本来本文的名字叫 《exec 系列函数》。可是想了想,exec 系列的函数有 6 个,实在是太多,而且功能也一样,实在没必要一一讲解。exec 系列函数的目的,就是把本进程空间的代码和数据全部替换成你指定的数据,然后从新程序的入口点开始执行。本篇只介绍其中一个函数——execvp.这里解释一下,函数名中的 v 代表 vector,表示参数是数组。p 代表 path,表示如果你指定的文件不包含路径,就原创 2016-12-19 22:03:07 · 2964 阅读 · 0 评论 -
41-新的信号注册函数 sigaction
在这之前,我们一直使用 signal 来注册信号处理函数,而且一开始我甚至都没有提起过甚至 signal 还有一个兄弟——sigaction. 我相信,把 sigaction 放到这里是适合的,因为你已经具备了足够的基础去理解它了。1. sigaction 函数不同于 signal 函数,sigaction 函数是符合 POSIX 标准的,而 signal 只是 ANSI C 标准函数。除了上面的区原创 2016-12-26 18:10:38 · 2358 阅读 · 4 评论 -
42-带参数的信号
前面不管我们是使用 signal 信号注册函数还是 sigaction 信号注册函数,我们都只注册了带一个参数的信号处理函数 void handler(int sig)。实际上,我们也可以使用带参数的的信号处理函数。signal 函数没办法注册一个带附加参数的信号处理函数,但是 sigaction 可以。具体是通过 sigaction 的第二个参数 struct sigaction 结构体来指定带附原创 2016-12-27 11:58:50 · 3086 阅读 · 0 评论 -
52-有名管道
有名管道打破了无名管道的限制,进化出了一个实实在在的 FIFO 类型的文件。这意味着即使没有亲缘关系的进程也可以互相通信了。所以,只要不同的进程打开 FIFO 文件,往此文件读写数据,就可以达到通信的目的。不过 FIFO 文件与我们最开始讲的本地文件通信还是有着本质的区别,它长着普通文件的脑袋,却有着无名管道的基因。1. 创建 FIFO 类型文件通过命令 mkfifo 创建如:$ mkfifo原创 2017-01-04 11:30:03 · 1882 阅读 · 6 评论 -
43-打通你的任督二脉-信号处理函数的执行期
可能有些同学会对信号处理函数是如何被操作系统调用的十分感兴趣,当然也有一部分同学不感兴趣的你可以跳过此篇啦。本文可能会涉及一些内核,x86 保护模式相关的知识,所以要求还是蛮高。不过我会尽量用最朴素的语言讲清楚。在这之前,有些概念需要简单的提一下。1. 系统调用当你使用系统调用的时候,一般就意味着你要进入操作系统内核了。比如 write 函数,read 函数,再比如 sigaction 函数等等。基原创 2016-12-27 18:32:03 · 3430 阅读 · 0 评论 -
53-System V 共享内存初体验
为了能快速掌握 System V IPC,本篇以最少量的文字让初学者先初步掌握共享内存,后续文章,再慢慢深入。共享内存只是 System V IPC 中的一种,前面的进程通信总览中我们讲过 System V IPC 包括了共享内存、消息队列和信号量。1. 共享内存为了能够快速上手共享内存,下面直接介绍一下大致的方法:根据已知的键(key) 使用 get 函数获取或者创建内核对象的 id 号。根据原创 2017-01-05 11:02:48 · 2034 阅读 · 2 评论 -
45-超越 goto 的跳转 longjmp
不明所以的同学可能觉得本篇和信号这一专题关系不大,实际上,本篇是为 sigsetjmp 和 siglongjmp 函数作铺垫。但是在这讲这两函数前,先学习更简单的 setjmp 函数和 longjmp 函数。1. 回忆 goto回忆 C 语言中的 goto 语句,它所起到的作用就直接从一条语句跳转到另一条语句。这种程序往往破坏了程序的结构,所以专家们都不提倡使用 goto 语句,不过这个我们并关心,原创 2016-12-28 15:24:48 · 1317 阅读 · 0 评论 -
46-打造自己的 longjmp
对于 longjmp 这种不走常规路线的迷一样的函数,到底是如何实现的呢?也许从你学习 C 语言以来你都不知道代码还可以这么写。其实,一切都是套路。通常来说,编译器为我们编译的函数,都是按正常套路来走的。这意味着,如果你用 C 语言编写函数,就会被编译器给套路掉。所以,这种不按套路走的函数,我们只能用汇编语言写了。为能能写出这种函数,需要掌握函数栈帧结构。1. 函数栈帧1.1 基本概念熟悉 C 语言原创 2016-12-28 22:11:47 · 2910 阅读 · 2 评论 -
48-信号大结局
信号这个专题花了太长的篇幅,也可能是目前你学的最累的一次,实验也非常多。这篇文章就帮我们理一理整个信号的脉络。信号专题总结从理解进程能够接收信号开始,就探讨了进程对信号做出的默认动作。接下来我们开始引入ANSI C提供的 signal 信号注册函数,帮助我们自己处理信号。掌握了信号处理函数,你就可以使用异步的方式处理子进程先行退出的情况了(SIGCHLD)。同时我们演示了信号的不可靠性,意思是说如果原创 2016-12-30 09:43:21 · 1360 阅读 · 0 评论 -
49-进程通信初步
错综复杂的信号专题终于结束,能写到这里,感觉真不容易,甚至有点小激动,因为接下来进入进程间通信这个老生常谈的大专题。希望能有信心写好,因为我自己也有很多地方没有弄清晰,希望借此笔记来提升一下自己。进程间通信,指的是不同的进程间进行交流,本质上就是进程之间发送和接收数据。本质上,信号也是属于进程间通信的一种,只不过信号这一块的内容实在是太多,所以自成一体了。作为进程通信的初步,我并不想以“管道通信”开原创 2016-12-29 21:46:01 · 2090 阅读 · 1 评论