C语言——linux编程(上)
目录
1、LInux操作系统
1.2、Linux操作系统的主要特点包括:
1.3、Linux操作系统的常见特点还有:
2、shell命令与Makefile
2.1、常见的shell命令
2.2、shell脚本
2.2.1、为什么使用shell脚本
2.2.2、怎么编写shell脚本
2.2.3、一些常用的shell脚本编写技巧:
2.2.4、示例
2.3、Makefile
2.3.1、Makefile的主要特点
2.3.2、使用Makefile的原因
2.3.3、示例
2.4Makefile与shell的区别
3、IO操作
3.1、缓冲
3.2、默认的IO
3.3、打开文件
4、库
4.1、库在编译中的作用
4.2、静态库
4.2.1、静态库的特点
4.2.2、静态库的制作
4.2.3、静态库的使用
4.3、动态库
4.3.1、动态库的特点
4.3.2、动态库的制作
4.3.3、动态库的使用
1、LInux操作系统
概念:操作系统是一款进行软硬件资源管理的软件
操作系统的意义在于它在计算机硬件和用户之间提供了一层抽象,使得用户和应用程序能够更高效、更安全地使用计算机资源
1.2、Linux操作系统的主要特点包括:
- 开源:Linux的源代码是开源的,这意味着开发者可以自由地查看、修改和分发代码。
- 免费:Linux操作系统是免费的,不需要付费使用。
- 可定制:Linux操作系统可以根据需要进行定制,包括添加或删除功能、修改界面等。
- 高安全性:Linux操作系统具有高安全性,因为它具有强大的访问控制机制和病毒检测功能。
- 高可靠性:Linux操作系统具有高可靠性,因为它具有自动故障检测和恢复机制。
- 广泛支持:Linux操作系统支持广泛的硬件平台和应用程序。
1.3、Linux操作系统的常见特点还有:
- shell命令:Linux操作系统使用shell命令来控制和管理系统。
- 文件系统:Linux操作系统使用文件系统来存储和管理文件。
- 进程管理:Linux操作系统使用进程管理来控制和管理进程。
- 网络管理:Linux操作系统使用网络管理来控制和管理网络。
2、shell命令与Makefile
2.1、常见的shell命令
文件和目录操作:
ls
: 列出目录内容。 常用选项如-l
(长格式),-a
(显示隐藏文件),-h
(以人类可读的格式显示文件大小)。cd
: 改变当前工作目录。pwd
: 显示当前工作目录。mkdir
: 创建目录。rmdir
: 删除空目录。rm
: 删除文件或目录。-r
选项递归删除目录及其内容,使用需谨慎!cp
: 复制文件或目录。mv
: 移动或重命名文件或目录。touch
: 创建空文件或更新文件时间戳。find
: 查找文件。 功能强大,选项众多,需要学习其用法。locate
: 快速查找文件(基于数据库,需要更新数据库)。
文件内容操作:
cat
: 显示文件内容。less
: 分页显示文件内容,方便阅读大型文件。head
: 显示文件开头几行。tail
: 显示文件结尾几行,-f
选项可以实时监控文件变化。grep
: 在文件中查找特定模式的行。 非常强大,支持正则表达式。sed
: 流编辑器,用于对文本进行编辑。awk
: 文本处理工具,擅长处理表格数据。
系统管理:
df
: 显示磁盘空间使用情况。du
: 显示目录或文件大小。ps
: 显示正在运行的进程。top
: 动态显示系统进程信息。kill
: 终止进程。shutdown
: 关闭或重启系统。reboot
: 重启系统。sudo
: 以root权限执行命令。apt-get
(Debian/Ubuntu) 或yum
(CentOS/RHEL) : 包管理工具,用于安装、更新和删除软件包。
网络:
ping
: 测试网络连接。ifconfig
或ip
: 查看网络接口信息。netstat
或ss
: 查看网络连接状态。wget
: 下载文件。
这只是一些最常用的命令,还有很多其他的命令可以根据你的需求学习和使用。 建议学习使用 man
命令查看命令的手册页,了解每个命令的详细用法和选项。 例如,输入 man ls
可以查看 ls
命令的手册页。
2.2、shell脚本
shell脚本是一种文本文件,包含一系列命令和控制语句,可以自动执行一系列操作。shell脚本通常以.sh
或.bash
为扩展名,使用shell语言编写。
2.2.1、为什么使用shell脚本
- 自动化任务:shell脚本可以自动执行一系列复杂的任务,提高工作效率和减少人工错误。
- 重复性任务:shell脚本可以重复执行相同的任务,减少人工劳动和提高效率。
- 可维护性:shell脚本可以轻松维护和修改,降低维护成本。
- 可扩展性:shell脚本可以轻松扩展和修改,适应新的需求和场景。
2.2.2、怎么编写shell脚本
- 选择shell类型:选择合适的shell语言,常用的有Bash、Zsh、Fish等。
- 写入命令:在脚本文件中编写命令,使用shell语言编写。
- 使用控制语句:使用控制语句,如if-else、for循环、while循环等,控制命令的执行顺序。
- 使用变量:使用变量存储数据,方便在脚本中使用。
- 测试脚本:使用
sh
命令或bash
命令执行脚本,测试脚本是否正确。 - 修复错误:根据错误信息修复脚本中的错误。
- 优化脚本:根据实际情况优化脚本,提高执行效率和可维护性。
2.2.3、一些常用的shell脚本编写技巧:
- 使用
#!/bin/bash
或#!/bin/sh
作为文件开头,指定shell类型。 - 使用
set -e
命令来设置退出OnError,脚本一旦错误就退出。 - 使用
set -x
命令来设置Debug模式,输出命令执行过程。 - 使用
if-else
语句来控制命令的执行顺序。 - 使用
for
语句来循环执行命令。 - 使用
while
语句来循环执行命令。 - 使用
trap
命令来捕捉信号,例如Ctrl+C。
2.2.4、示例
#!/bin/bash
# 读取用户输入的文件个数
read -p "请输入要创建的文件个数:" num
# 创建文件
for ((i=1; i<=$num; i++)); do
# 创建文件
touch file${i}
# 在文件中写入该文件是第几个
echo "This is file i">>filei" >> filei">>file{i}
done
使用 bash 编写的 shell 脚本,实现批量创建文件,并在每个文件中写入该文件是第几个;
保存这个脚本到一个文件中(例如 create_files.sh
),并将其设置为可执行文件:
chmod +x create_files.sh
最后直接运行该文件,就可以实现脚本批量创建文件了
2.3、Makefile
Makefile是一个自动化编译和构建的工具,它可以根据依赖关系来自动编译和构建项目;
Makefile中使用时间戳可以帮助确定文件是否需要重新编译
2.3.1、Makefile的主要特点
- 可以自动化编译和构建过程,使得开发人员可以专注于编写代码,而不是手动编译和构建。
- 支持依赖关系,使得Makefile可以根据项目的依赖关系来自动编译和构建。
- 可以灵活地配置编译和构建参数,例如编译器、编译器选项、输出文件等。
- 可以在多个平台上使用,例如Linux、Unix、Windows等。
2.3.2、使用Makefile的原因
- 提高编译和构建效率:Makefile可以自动化编译和构建过程,使得开发人员可以快速地编译和构建项目。
- 提高代码可维护性:Makefile可以根据依赖关系来自动编译和构建,使得开发人员可以更好地理解和维护代码。
- 提高项目的可重复性:Makefile可以确保项目的编译和构建结果是一致的,使得开发人员可以更好地控制项目的构建过程。
- 提高项目的可扩展性:Makefile可以灵活地配置编译和构建参数,使得开发人员可以根据需要来调整编译和构建过程。
2.3.3、示例
CC=gcc
CFLAGS=-c
all: main main_share
main: main.o func.o
$(CC) main.o func.o -o main
cp main ./share/
main.o: main.c func.h
(CC)(CC) (CC)(CFLAGS) main.c
func.o: func.c func.h
(CC)(CC) (CC)(CFLAGS) func.c
main_share: main
cp main ./share/
clean:
rm -f main main.o func.o
rm -f ./share/main
这个 Makefile 做的事情是:
- 编译
main.c
和func.c
生成对象文件main.o
和func.o
。 - 将对象文件编译成可执行文件
main
。 - 将可执行文件复制到
./share/
文件夹。 - 定义一个目标
clean
,用来删除编译产生的文件。
终端输入make,就进行编译产生需要的文件,make clean就可以删除编译产生的文件
2.4Makefile与shell的区别
Makefile和shell是两种不同的编程语言和工具。
Makefile是专门用于编译、链接和管理大型项目的脚本语言。它使用Make工具来自动化编译和构建过程,可以根据依赖关系和目标文件来确定编译顺序和步骤。Makefile通常用于大型软件项目、操作系统、数据库等领域。
Shell是命令行接口,可以执行系统命令、脚本和程序。Shell语言使用一种称为shell script的脚本语言,可以在命令行中执行命令、读取文件、处理数据等。Shell通常用于系统管理、脚本编写、自动化任务等领域。
以下是Makefile和shell的一些主要区别:
- 目的:Makefile主要用于编译和构建大型项目,shell主要用于执行系统命令和脚本。
- 语言:Makefile使用Make语言,shell使用shell script语言。
- 逻辑结构:Makefile使用规则和目标文件来描述编译过程,shell使用命令和脚本来描述执行过程。
- 执行方式:Makefile使用Make工具来执行编译和构建过程,shell使用shell interpreter来执行脚本和命令。
总的来说,Makefile和shell都是编程语言,但它们有不同的使用场景和特点。
3、IO操作
前面的帖子中,已经介绍了标准IO与系统IO就不从头说起了
我们直接深入一点介绍一些需要注意的点
3.1、缓冲
-
标准IO的缓冲:标准IO 库(如
stdio.h
)通常会自动管理缓冲区,以提高文件操作的效率。缓冲区可以是全缓冲、行缓冲或无缓冲。- 全缓冲:数据在缓冲区满时才会写入文件。
- 行缓冲:每次遇到换行符时写入文件。
- 无缓冲:数据直接写入文件,没有缓冲。
-
系统IO的缓冲:系统IO 没有自动缓冲机制,需要程序员手动管理缓冲区。这意味着每次读写操作都会直接与文件系统交互,性能较低。
3.2、默认的IO
在我们使用文件描述符的时候会发现,文件描述符表现就是一个整数,虽然他是一个结构体,但是我们可以当作一个结构体类型的整数来使用。
那么在使用过程中,有没有细心的小伙伴发现,文件IO的文件描述符是从3开始增加的呢?
那么 0、1、2去那里了??默认从3开始吗?
其实0、1、2是默认打开的文件IO,他们分别是标准输入,标准输出,标准错误
3.3、打开文件
不同的文件打开模式(如读写、只读、只写)可能会影响IO操作的结果;
所以我在OPEN的时候,就需要想好我们对文件进行什么操作
4、库
Linux库是一些预编译好的代码集合,包含函数、变量和数据结构等,可以被多个程序共享使用。它们类似于积木块,可以简化程序开发,提高代码复用率,并减少程序的体积。
linux下的库有两种:静态库和共享库(动态库)。二者的不同点在于代码被载入的时刻不同。
静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库,因此体积较大。
动态库在程序编译时并不会被连接到目标代码中,而是在程序运行时才被载入,因此在程序运行时还需要动态库存在,因此代码体积较小。
4.1、库在编译中的作用
- 代码复用: 程序员无需重复编写已有的功能代码,可以直接使用库中提供的函数和数据结构。
- 模块化开发: 库将代码组织成模块化的单元,提高代码的可维护性和可扩展性。
- 提高效率: 库通常是用优化过的代码编写,可以提高程序的运行效率。
- 链接过程: 编译器在编译程序时,会将程序使用的库函数链接到程序中,生成可执行文件。这需要链接器完成。 静态链接将库代码直接复制到可执行文件中,动态链接则是在运行时加载库。
4.2、静态库
4.2.1、静态库的特点
- 独立性: 可执行文件独立于静态库,无需外部依赖。
- 体积: 可执行文件体积较大,因为包含了所有库代码。
- 更新困难: 更新静态库需要重新编译整个程序。
- 版本冲突: 多个程序使用不同版本的同一静态库可能导致冲突(虽然概率较低,因为静态链接会在编译时解决符号问题)。
- 空间浪费: 如果多个程序使用同一个静态库,每个程序都会包含一份库代码的副本,造成空间浪费。
4.2.2、静态库的制作
通常,静态库的后缀名为.a
(在Linux下) 或 .lib
(在Windows下)。制作静态库一般需要以下步骤:
- 编写代码: 编写需要打包成静态库的源代码文件(例如,
.c
或.cpp
文件)。 - 编译成目标文件: 使用编译器将源代码编译成目标文件(例如,
.o
文件)。 这通常使用gcc -c *.c -o *.o
命令完成。 - 创建静态库: 使用
ar
命令将目标文件打包成静态库。例如:ar rcs libmylib.a *.o
这将创建名为libmylib.a
的静态库。
4.2.3、静态库的使用
在编译程序时,需要链接静态库。例如,使用 gcc main.c -L. -lmylib -o myprogram
命令编译 main.c
文件,并链接 libmylib.a
静态库。
-L.
指定库文件的搜索路径为当前目录。-lmylib
指定链接的库名为libmylib.a
(注意去掉lib
前缀和.a
后缀)
4.3、动态库
4.3.1、动态库的特点
- 可以被多个程序共享:因为动态库在程序运行时被加载到内存中,所以多个程序可以共享同一个动态库,减少了内存的占用。
- 可以在程序运行时被加载:动态库可以在程序运行时被加载,而不是在编译时。
- 可以被卸载:动态库可以在程序运行时被卸载,从而释放内存。
4.3.2、动态库的制作
- 创建一个库文件:使用编译器创建一个库文件,例如使用 GCC 创建一个
.so
文件。 - 定义库的接口:在库文件中定义库的接口,以便其他程序可以使用。
- 编译库文件:编译库文件以生成一个可执行文件。
- 创建一个共享对象文件:使用
objdump
或objcopy
工具将可执行文件转换为一个共享对象文件。
4.3.3、动态库的使用
- 在程序中包含库文件:在程序中包含库文件,以便程序可以使用库的接口。
- 链接库文件:使用链接器将库文件链接到程序中。
- 在程序中使用库接口:在程序中使用库的接口,以便实现所需的功能。
在 Linux 中,可以使用以下命令创建一个动态库:
gcc -shared -o libmylib.so mylib.c
然后,可以在程序中使用以下命令链接库文件:
gcc -o myprogram myprogram.c -L. -lmylib
其中,-L.
指示链接器在当前目录中搜索库文件,-lmylib
指示链接器链接 libmylib.so
库文件。