第一章 Linux基础
库函数与系统调用
- 库函数:是在系统调用上层的函数,库函数一般程序员可以使用的通用函数。虽然这些库函数可能会调用一个或多个内核的系统调用,但是它们并不是内核的入口点。
- 在Linux下,每个系统调用由两部分组成:
核心函数:是实现系统调用功能的代码,作为操作系统的核心驻留在内存中,是一种共享代码,运行在核心态。
接口函数:是提供给应用程序的API,以库函数的形式存在于Linux的库lib.a中,该库中存放了所有系统调用的接口函数的目标代码,用汇编语言书写。 - 可以这样理解:系统调用与库函数从形式上来说是一样的,都以C语言函数形式存在,但系统调用比库函数更底层;或许从用户角度来看它们完成的功能相同,然而从实现着角度来看差别很大。
Linux常用命令
useradd命令
- useradd [选项] 用户名
- 新建用户账号
passwd命令
- passwd [-dkls][-u[-u<-f>][用户名]
- 设置密码
userdel命令
- userdel [-r] 用户名
- 删除指定的用户账号,只有超级用户才能使用此命令
groupadd命令
- groupadd [选项] 组名
- 新建组,只有超级用户才能使用此命令
groupdel命令
- groupdel 组名
- 删除指定的组,只有超级用户才能使用此命令。
mkdir命令
- mkdir [选项] 目录
- 创建目录
mv命令
- mv [选项] 源文件或目录 目的文件或目录
- 移动或重命名文件或目录。
cp命令
- cp [选项] 源文件或目录 目的文件或目录
- 复制文件或目录
rm命令
- rm [选项] 文件或目录
- 删除文件或目录
chmod命令
- 格式一:chmod 数字模式 文件
- 格式二:chmod 功能模式 文件
- 修改文件的访问权限
chgrp命令
- chgrp 组 文件
- 修改文件所属的组
chown命令
- chown 文件所有者[.组] 文件
- 改变文件的所有者,也可以一并修改文件的所属组
ps命令
- ps [选项]
- 显示进程的状态。无选项时,显示当前用户在当前终端启动的进程。
kill命令
- kill [选项] 进程号
- kill %作业号
- 终止正在运行的进程或作业
man命令
- man section 命令名
- 显示命令的帮助信息。
第二章 Linux系统开发环境
Vi编辑器
- 一类说法: Vi编辑器的工作模式:插入模式、命令模式、末行模式
- 另一类说明:插入模式和命令模式
退出Vi编辑器
q:如果当前文件没有被修改过,将直接退出vi,否则会提示信息且并不退出Vi
wq:保存当前文件并退出Vi
q!:直接退出Vi,即使当前文件被修改过,也不保存修改内容
GCC编辑器
通过编译、链接工具将该源程序转换成可执行文件。Linux系统下主要的编辑器是GCC。
GCC编译器能将C、C++语言源程序和目标程序编译、链接成可执行文件,如果没有给出可执行文件的名字,则GCC将生成一个名为"a.out"的文件。
GCC识别的文件类型
GCC编译器的基本工作过程
- GCC将C语言源文件生成可执行文件的过程:预处理、编译、汇编和链接。
1、调用“cpp”进行预处理。
2、调用“cc1”进行编译,这个阶段根据输入文件生成以“s”为后缀的汇编代码文件。
3、汇编过程是针对汇编语言的步骤,调用"as"进行工作。“.s”为后缀的汇编语言源代码文件经过预编译和汇编之后生成.o为后缀的目标文件。
4、当所有的目标文件都是生成之后,GCC调用ld来完成最后的关键性工作,这个阶段就是链接。
Makefile文件的命名
make命令会在工作目录(执行make命令的目录)下按照文件名顺序寻找Makefile文件读取并进行,查找的文件名顺序为:GNUmakefile,makefile,Makefile。
通常应该使用“makefile”或“Makefile”作为Makefile(推荐使用)的文件名。
make命令指定Makefile文件的格式:
make -f NAME
静态库和共享库
- 静态库和共享库都是由.o文件创建的,因此都要先将.c源文件生成目标文件。
- 静态库的创建
分别生成目标文件fun1.o,fun2.o
生成静态库(libxxx.a) - 静态库的使用
gcc -o test_s test.c -L .-lxxx -static - 共享库的创建
分别生成目标文件fun1.o , fun2.o
生成共享库(libxxx.so) - 共享库的使用
gcc -o test_d test.c -lxxx
静态库和共享库的区别
静态库:一般以.a结尾,lib test.a 编译时:库函数被合并在可执行文件中
执行时:提供可执行文件即可,可执行文件会变大,适合小程序调用。
共享库:一般以.so或.so.x结尾,x代表版本号,lib test.so.1
编译时:库文件不被合并入可执行文件
执行时:提供可执行文件和库文件才可执行
可执行文件会比较小,并且几个可执行文件可以共享库,适合大型项目。
第三章 Linux程序设计初步
- Linux平台下可执行文件的类型是普通文件,其文件格式有3种:a.out(汇编器和链接编辑器的输出)、COFF(通用对象文件格式)、ELF(可执行和链接格式)
- 可执行文件包含:代码段、数据段、BSS段
- 代码段:主要保存程序执行代码,通常是只读的,如果程序创建了多个进程,则各个进程可以共享代码段。
- 数据段:保存已经初始化的全局变量、静态变量
- BSS段保存未初始化的全局变量、静态变量,并在程序开始执行之前被内核初始化为0或空指针NULL。
进程在内存中的映像主要分为:
代码段(text)、数据段(data)、 BSS段、堆(heap)、栈(stack)
变量的类型修饰符
-
C语言在声明变量的常见格式为:
[类型修饰符] 数据类型 变量名 -
常见的类型修饰符有:auto、const、register、static、volatile、extern。
-
其中static和extern还可以用来定义函数。auto可以不必显示写出,即没有指定类型修饰符的变量都是auto变量。
-
特殊修饰变量的存储位置 p42
命令行参数及获取
- 每一个程序都有一个程序入口,C语言中使用main函数作为程序执行的入口
- 当用户执行程序时,除非环境变量PATH中已经包含程序所在的路径,否则都需要输入程序的路径名,而不仅仅是程序本身的名字(这里的路径名可以是相对路径也可以是绝对路径)
- 通常,main函数在使用时可以不带参数;但如果程序需要获取用户在运行程序时指定的命令行参数,就需要main函数带参数。
- main函数的前两个参数argc和argv传递了命令行参数信息;第3个参数env代表环境变量的指针数组,用于获取系统传递给进程的环境变量值。
项目 | 描述 |
---|---|
原型 | int main(int argc,char *argv[]) |
功能 | 程序入口函数 |
参数 | argc:代表命令行参数个数,该数目包括程序名在内,也就是说argc至少为1 argv:是一个字符指针数组,代表指向包括程序名的各个命令行各参数项字符串地址,数组有效元素个数为argc。如果命令行参数有多个,则argc[0]代表程序名,argv[1]~argv[argc-1]依次指向其他各项参数项字符串,argv[argc]值为NULL,代表字符指针数组结尾 |
返回值 | int类型,代表应用程序的退出状态 |
环境变量
Shell变量
- Shell是一个特殊的进程,是用户与内核之间的接口
- Shell中对环境变量的操作主要包括查看、定义、修改、删除
- 查看: echo $变量名
- 定义:变量名=变量值
- 修改:export PATH=$PATH
- 删除:unset 变量名
环境变量
- 如果使用命令方式访问环境变量,则要在命令行上输入命令,并且修改的是Shell的环境变量。
时间管理
- Linux内核提供的时间是从国际标准时间(UTC)公元1970年1月1日0时0分0秒开始以来经过的秒数,被称为日历时间,数据类型为time_t。
struct tm
{
int tm_scc; //秒,范围0~61,2秒闰秒
int tm_min; //分,范围0~59
int tm_hour; //小时,范围0~23
int tm_mday; //一个月内的日期,范围1~31
int tm_mon; //月份,范围0~11
int tm_year; //年,自1900年开始计算,如198相当于2008
int tm_wday; //星期,范围0~6
int tm_yday; //一年中的日期,范围0~365
int tm_isdst; //夏令时标记(>0夏令时有效,0无效,-1不可用)
}
第四章 文件I/O
UNIX/Linux文件系统
- UNIX系统及类UNIX系统采用称为UFS的文件系统,UNIX文件系统分为4个部分:引导块、超级块、索引节点表及数据块区。
- UNIX/Linux中,每个文件分为两部分:索引节点(i节点)及文件数据块部分。索引节点用于记录文件的各种属性文件。
- Linux常见的文件类型有:普通文件、目录文件、字符设备文件、块设备文件、FIFO(管道)文件、符号链接文件和套接字文件。
Linux系统定义了文件类型的宏及八进制码
S_IFMT 0170000 文件类型字段的二进制掩码
S_IFSOCK 0140000 Socket文件
S_IFLNK 0120000 符号链接文件
S_IFREG 0100000 常规文件(普通文件)
S_IFBLK 0060000 块设备文件
S_IFDIR 0040000 目录文件
S_IFCHR 0020000 字符设备文件
S_IFIFO 0010000 FIFO文件
Linux系统中定义的权限相关的宏及八进制码
文件I/O的基本操作
- 打开创建文件:open/creat
- 读文件:read
- 写文件:write
- 文件定位:lseek
- 关闭文件:close
文件的修饰符
- sync、fsync、fdatasync用于文件访问的同步。
- sync:将缓冲区中的内容写入磁盘,无参数、无返回值
- fsync、fdatasync:将指定文件的内容写入磁盘,参数:fd要同步的文件的文件描述符。返回值:如果成功,则返回0;如果失败,则返回-1,并且errno为错误码
第五章 文件属性
stat、fstat和lstat的区别
- 系统调用stat通过给出文件名来获取该文件属性,而fstat则通过文件描述符来获取文件属性。因此,fstat在使用前,应首先使用open打开该文件并得到该文件的文件描述符,而stat并不需要事先打开文件。lstat是专门用于获取符号链接文件本身的属性的。
用户/组ID与名字的转换
- Linux是一个多用户、多任务的操作系统
- 在Linux系统中,可以创建若干个用户
- 用户组(group)就是具有相同特征的用户的集合体
- 执行ls -l命令,可以得到的文件信息,包括文件的所有者名及所属组组名。
硬链接与符号链接的区别
-
(1)命令:
硬链接命令:ln 源文件 硬链接文件(不能对目录创建硬链接)
软链接命令:ln -s 源文件/目录 符号链接文件 -
(2)新增文件:
硬链接:不新增真实的文件,仅增加一个指向源文件inode的文件名
符号链接:增加一个真实的文件即符号链接文件,新增的符号链接文件有自己的inode文件内容为设置符号链接时指定的源文件或目录的路径名。 -
(3)删除源文件/目录
硬链接:删除原文件,使文件对应inode的链接数减1,减为0则删除该文件。
符号链接:删除原文件,符号链接文件失效,但该文件依然存在,如果后期又新建了一个与符号链接文件内容相同路径的文件,则符号哦链接文件重新有效 -
(4)删除链接文件
删除硬链接文件:使文件对应inode的链接数减1,减为0则删除该文件
删除符号链接文件:对原文件/目录无任何影响 -
(5)是否跨文件系统
硬链接:不可以,不同的文件系统其文件的组织方式和结构可能不一样,因此不能随意创建跨文件系统的硬链接文件
符号链接:可以,因为符号链接文件仅仅保存了原文件或目录的路径名,所以不受文件系统的影响。
第六章 目录文件管理
目录基本操作
- 目录也是Linux系统的一种文件类型,其内容也是该目录中文件名和文件索引节点编号的对应关系。
- 不能对文件目录进行写操作,当用户在一个目录下执行了创建/删除文件或目录的操作,系统会对目录文件的内容进行修改,用户不能自己直接修改目录文件。
- 打开目录:opendir
- 读目录:readdir
- 关闭目录:closedir
目录其他操作
- 切换当前目录:chdir/fchdir
- 创建目录:mkdir
- 删除目录:rmdir
- 目录指针定位:telldir、seekdir、rewinddir
第七章 进程控制
进程基本概念
- 进程是具有一定独立功能的程序关于某个数据集合的一次运动活动。它是操作系统动态执行的基本单元。
- 进程主要有两点:第一,进程是一个实体。每一个进程都有它自己的地址空间,一般情况下,包括文本区域、数据区域和堆栈区域。第二,进程是一个“执行中的程序”、
- 进程的特性:
动态性、并发性、独立性、异步性 - 进程控制块:PCB,进程标识符、相关的文件描述符、进程状态、接收的信号
- 进程的状态:就绪、执行、等待
进程标识
- 进程标识为0和1,最大pid:32767,最小pid:-1
- 进程0是内核态进程,成为idle进程或swapper进程。
- 由进程0创建1号进程,1号进程负责执行内核的部门初始化工作及进行配置。
- 每个进程都有一个唯一的父进程。
用户标识
- 通常每个用户有一个唯一的用户ID,用户ID为0的用户为根(root)或超级用户(super user)
- getuid获取当前实际用户ID或有效用户ID,无参数,getuid返回实际用户ID,geteuid返回有效用户ID
- getgid获取当前实际用户组ID或有效用户组ID;无参数,getgid返回实际用户组,getegid返回有效用户组ID。
进程控制
- vfork和fork的区别:调用vfork不会将父进程的数据空间复制到子进程中,子进程与父进程共享数据空间,父进程等待子进程先执行。子进程中如果不调用exec*系列函数,则需要调用_exit系统调用
- exec*系列函数不会创建新锦成,而是用新的程序替换子进程的地址空间,包括:代码段、数据、堆、栈。新进程的pid保持不变,新进程从main函数开始运行。
- Linux系统提供了6个exec字母开头的函数,execve是系统调用,另外5个函数是库函数。
进程终止
- 一共5种进程终止原因,其中3种为正常终止,2种为异常终止
- 正常终止:
main函数中执行return语句
调用exit函数
调用_exit系统调用 - 异常终止:
调用abort函数
当进程接收到某种信号,如内存越界访问。
进程等待结束
- 状态改变:子进程终止;由于收到信号,子进程停止;由于收到信号,子进程继续运行。
- wait:等待子进程结束,参数:子进程结束时返回的终止状态;返回值:结束子进程的pid
- WIFEXITED(status):如果子进程正常终止,则返回true
- WEXITSTATUS(status):返回子进程的退出状态
- WIFSGNALED(status):如果子进程被某个信号终止,则返回true
- 如果子进程不存在,则父进程调用wait后立即返回,返回值为-1
system函数
- system加载执行Shell命令:参数command,要加载执行的命令;命令执行失败返回-1
第八章 线程
线程的概念
线程称为轻量级进程。进程是资源分配的最小单位,而线程是计算机中独立运行、CPU调度的最小单元。
线程基本操作
pthread_create:创建新进程
pthread_self:获取线程ID
pthread_exit:线程退出
pthread_join:线程等待
第九章 信号与管道
信号的概念
信号是一个32位整数值,代表一个简单信息。
信号的产生
- 用户操作
- 进程执行出错
- 进程执行某个系统调用或函数
- 生成
- 传递
kill系统调用
- kill系统调用允许进程将信号发送给某个进程或进程组。
- raise函数只能给进程自己发送信号
信号的响应方式
- 忽略信号
- 执行系统默认动作
- 捕捉信号
sleep函数
- sleep:当前进程睡眠指定的描述;参数:seconds要睡眠的秒数;返回值:睡眠结束时返回0,否则返回睡眠剩余时间
- 经过了seconds指定的描述,此时sleep返回0
- 捕捉到一个信号并从信号处理函数返回,此时sleep返回剩余的秒数。
pause函数
- pause:暂停并等待信号,无参数,返回值:当捕获到信号时,返回-1
管道
- 特征:
管道是半双工的,即通过管道可以实现两个方向的数据流,但通信时只有一个方向的数据流
使用管道进行通信的两个进程一定要有共同的祖先进程 - FIFO有名管道。
- 无名管道
第十章 进程间通信
进程间通信
- IPC(信号和管道),信号量、共享内存、消息队列及套接字网络通信
- System V支持的3种进程间通信方式:消息队列、共享内存、信号量
IPC简介
- IPC资源只在本机通信中使用,不能跨网络
- IPC资源生存期与内核相同
- 每个IPC资源都有一个关键字key
- 每个IPC资源都有一个结构体Xid ds 记录其属性
- 可使用ipcs显示状态、ipcrm删除对象
- 访问权限:读、写,没有执行
- 3种IPC资源有类似的系统调用
信号量
- 信号量是一种比较特殊的IPC,它是一个计数器
- IPC操作信号量的3个相关系统调用有3个:semget、semctl、semop
- semget用于创建新的信号量集或打开已存在的信号量集。
- semctl用于信号量集的控制操作
- semop用于信号量操作
共享内存
- 共享内存相关的系统调用有4个:shmget、shmat、shmdt和shmctl
- shmget用于创建共享内存或打开已存在的共享内存
- shmat用于把共享内存区域映射到调用进程的地址空间
- shmdt用于断开共享内存区域与调用进程之间的关联
- shmctl用于对共享内存的控制
消息队列
- 消息由两部分组成:固定大小的消息首部、可变长度的消息正文
第十一章 网络编程
网络编程的基本概念
- ifconfig命令用于查看和更改网络接口的地址和参数,包括IP地址、网络掩码、广播地址,使用权限是超级用户。
- ping命令用于检测主机网络接口状态,使用权限是所有用户
- netstat命令用于检查整个Linux网络状态
- route命令用于表示手工产生、修改和查看路由表