Linux系统编程01-简介、GCC与常用路径
简介
如何理解系统编程?
- 分析程序
- 学习系统调用
- 编程实现
内核提供的系统资源与服务
- 处理器(Processor)
内核安排一个程序何时开始、暂停、恢复、终止 - 输入输出(I/O)
程序中的所有输入输出数据必须流经内核,保证了正确性、有效性、安全性 - 进程管理(Process Management)
新建进程、终止进程、进程调度等都是内核的任务 - 内存(Memory)
内存管理:分配、回收、阻止内存被其他进程非法访问 - 设备(Device)
内核能屏蔽掉不同外设操作方式的差异 - 计时器(Timers)
内核通过系统调用向应用程序提供计时器服务 - 进程间通信(Interprocess Communication)
内核提供进程间通信的服务 - 网络(Networking)
网络通信是进程间通信的特殊形式,由内核提供服务
Linux多用户工作
用户名密码通过验证,系统启动shell进程,把用户交给这个进程,由该进程处理用户请求,每个用户有专属的shell进程,shell与用户之间的连接由内核控制,用户注销时,内核结束分配给该用户的进程。
一些常用的指令
目录类操作指令:
ls
cd
pwd
mkdir
rmdir(空目录)
文件操作:
cat
more
less
pg
cp
rm
mv
lpr(打印文件)
fortune程序:
fortune cookie, 带有祝福或哲理的纸条
bc命令:计算器
可以处理很大的数,能进行幂运算 100^3, 支持编程
后台运行:
ctrl+z 可以后台运行并且处于暂停状态,
jobs 命令可以查看当前由多少后台运行的命令,显示任务ID
输入 fg 命令可以把后台命令在恢复前台执行,也可以根据ID指定恢复
文件的权限结构
r w x r w x r w x
user group other
r:read w:write x:excute
GCC
GCC(GNU Compiler Collection) GNU编译器套件, 支持C的"方言", 可用命令行选项来控制编译器在翻译源代码时应该遵循哪个 C 标准。当使用命令行参数-std=c99
启动 GCC 时,编译器支持 C99 标准。
安装: sudo apt install gcc g++
查看版本: gcc/g++ -v/--version
GCC工作流程
GCC常用参数
gcc编译选项 | 说明 |
---|---|
-E | 预处理指定的源文件, 不进行编译 |
-S | 编译指定的源文件, 但不进行汇编 |
-c | 编译,汇编指定的源文件, 但是不进行链接 |
file2 -o file1 | 将文件file2 编译成可执行文件file1 |
-I directory | 指定include包含文件的搜索目录 |
-g | 编译时生成调试信息 |
-D | 程序编译时, 指定一个宏 |
-w | 不生成警告信息 |
-Wall | 生成所有警告信息 |
-On | n取0~3, 编译器的4个优化级别, -O0无优化, -O3基本最高 |
-l | 程序编译时, 指定使用的库 |
-L | 指定编译时, 搜索库的路径 |
-fPIC/fpic | 生成与位置无关的代码 |
-shared | 生成共享目标文件, 通常用在建立共享库时 |
-std | 指定C方言 , -std=c99 |
一些重点路径
Linux中存储系统程序的标准路径:
- /bin: 二进制文件目录, 存放启动系统时程序
- /usr/bin: 用户二进制文件目录, 存放用户使用程序
- /usr/local/bin: 本地二进制文件目录, 存放软件安装程序
用户应用程序:
- /usr/bin
- /usr/local/bin
- /opt
头文件:
- /usr/include (C语言)
- /usr/include/linux (特定Linux版本头文件)
- /usr/include/c++ (GNU C++)
编译时, -I 标志指定非标准位置的头文件目录
gcc -I/usr/openwin/include fred.c
可以用grep搜索某函数原型头文件:
cd /usr/include
; grep EXIT_ *.h
stdlib.h:#define EXIT_FAILURE 1 /* Failing exit status. */
stdlib.h:#define EXIT_SUCCESS 0 /* Successful exit status. */
库文件:(预先编译好的函数集合)
- /lib
- /usr/lib
库文件名字以lib开头, .a静态库, .so共享库, 可以通过完整库文件路径或 -l 标志指定库:
gcc -o fred fred.c /usr/lib/libm.a
gcc -o fred fred.c -lm
代表标准库目录中名为 libm.a 的库
使用 -L 标志增加库搜索路径:
gcc x11fred.c -o x11fred -L/usr/openwin/lib -lX11
用 /usr/openwin/lib 目录中 libX11 库来编译连接程序 x11fred
静态库
- 生成目标文件
gcc -c *.c
- ar程序创建归档文件(archive)
ar crv libfoo.a bill.o fred.o
- c:创建一个新的归档文件。如果指定的归档文件已经存在,则替换它。如果归档文件不存在,则创建一个新的归档文件。
- r:向归档文件中插入(或替换)文件。如果指定的文件已经存在于归档文件中,则替换它。否则,将该文件插入到归档文件的末尾。
- v:显示详细的操作信息。执行操作时,会显示每个插入或替换的文件的名称。
- 链接静态库
gcc -o program program.o libfoo.a
, 或者指定库目录文件的方式gcc -o program program.o -L. -lfoo
- 使用nm命令查看目标文件/函数库/可执行文件中包含的函数
nm libfoo.a
,nm program.o
共享库
- 创建共享库libfoo.so
gcc -shared -fPIC -o libfoo.so bill.c fred.c
(-fPIC 表示生成位置独立的代码(Position Independent Code,PIC)。生成的代码可以在内存中的任何位置加载和执行,而不依赖于特定的内存布局。这个选项告诉编译器生成适用于共享库的代码。) - 链接共享库创建可执行文件
gcc -o program program.c -L. -lfoo
- 运行程序报错:
./program: error while loading shared libraries: libfoo.so: cannot open shared object file: No such file or directory
- 设置库目录:
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
或者sudo mv libfoo.so /usr/lib
- 使用 ldd 查看一个程序的共享库
ldd program
linux-vdso.so.1 (0x00007ffc6affe000)
libfoo.so => ./libfoo.so (0x00007fccedfca000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fcceddce000)
/lib64/ld-linux-x86-64.so.2 (0x00007fccedfd6000)
man 文档
man文档分为8个小节,每个小节包含了不同的内容,具体如下:
- 用户命令(常用的命令,比如ls、cd等)
- 系统调用(与操作系统内核交互的函数)
- C库函数(标准C库中的函数)
- 特殊文件(通常是/dev目录下的设备文件)
- 文件格式和约定(文件格式,比如passwd文件的格式,以及约定,比如man文档的格式)
- 游戏和屏幕保护程序
- 杂项(包括许多的惯例和协议,比如mailcap文件的格式)
- 系统管理命令和守护进程(系统管理工具,如mount、reboot等)