《Unix/Linux系统编程》教材学习笔记第一章、第二章

chapter1


一、关于Unix、Linux和Windows

1. Unix是一种通用型操作系统,采用PDP-11微型计算机开发,有许多个版本。

  • AT&T Unix
  • Berkeley Unix
  • HP Unix
  • IBM Unix
  • Sun Unix

2. Linux是一个类Unix开源系统,最初由李纳斯基于Intel x86的个人计算机开发的一个实验性内核,目前也存在多个版本。

  • Debian Linux
  • Ubuntu Linux
  • Linux Mint
  • 基于RPM的Linux
  • Slackware Linux

chatgpt延伸:Windows是世界上最流行的操作系统,由微软公司开发,是一种图形用户界面操作系统,为人们的工作生活带来不少便利,现在最新版为Win11,不久微软将会推出Win12。历史版本如下:

  • Windows 1.0:1985年首次发布的初始版本。
  • Windows 3.0和3.1:在1990年代早期广受欢迎的版本,引入了多任务处理和图形用户界面。
  • Windows 95:1995年发布,引入了开始菜单和任务栏等标志性功能。
  • Windows 98:1998年发布,是Windows 95的升级版本。
  • Windows XP:2001年发布,被广泛认为是Windows历史上最成功的版本之一。
  • Windows Vista:2007年发布,引入了新的用户界面和安全功能。
  • Windows 7:2009年发布,受到了Windows XP用户的欢迎,具备更稳定的性能和改进的用户体验。
  • Windows 8和Windows 8.1:2012年发布,引入了新的触摸友好界面。
  • Windows 10:2015年发布,是目前(截止到我的知识截止日期)最新的主要版本,注重跨平台兼容性和云集成。
  • Windows 11:2021年10月5日发布。
  • Windows 12:尚未发布,但计划从2022年3月开始。

二、安装虚拟机、配置及使用

1.安装与配置虚拟机的教程网上一搜就有,这里给出两个较为详细的链接:

2.调整屏幕分辨率

进入Linux系统后打开终端输入`xdiagnose`。在X诊断设置窗口中,启用Debug下所有选项,包括:

- 附加图形调试消息
- 显示启动消息
- 启用自动崩溃错误报告

注意:在使用上面的命令时需要用户权限,因此请输入`sudo xdiagnose`来使用此命令。



进行如上操作后,再将虚拟机的屏幕尺寸修改后就能生效。

3.安装C语言集成环境

使用`sudo apt-get install emacs`来安装用于C语言开发集成环境。

4.使用Ubuntu Linux的一些注意要点

- 使用Ctrl+Alt+T打开伪终端
- 用户默认为普通用户,而不是超级用户,若需要使用特殊命令需要使用`sudo command`
- 运行一个当前目录中的可执行文件命令为`./a.out`
- 一般安装的Linux版本为64位,若需要生成32位需要使用`gcc -m32 t.c # compile t.c into 32-bit code`
- 使用sh脚本大部分情况比直接操作GUI界面方便

三、了解Unix/Linux文件系统组织

Unix/Linux文件系统采用树形组织结构
其文件类型如下:

1.目录文件:包含其他目录

2.非目录文件:可以是REGULAR文件,也可以是SPECIAL文件,但只能是叶节点
非目录文件还可以分为如下:

	- 字符特殊文件
	- 块特殊文件
	- 其他类型

3.符号链接文件:指向其他文件的指针

文件路径名

Unix/Linux文件系统树的根节点(/)称为根(目录),每个节点路径可表示为:`/a/b/c/d OR a/b/c/d`,以“/”开头的路径名为绝对路径名,反之为相对路径名。

Unix/Linux命令

常用命令如下:

ls dir:打印目录下内容
cd dir:跳转目录
pwd:打印绝对路径
touch file:改变文件名时间戳(若没有就创建)
cat file:显示文件内容
cp src dest:复制文件
mv src dest:移动或重命名文件
mkdir dir:创建目录
rmdir dir:删除(空)目录
rm file:删除文件
ln old new:链接文件
find:搜索文件
grep:搜索包含
ssh:远处登录主机
gzip file:压缩为.gz
gunzip file.gz:解压.gz
tar -zcvf file.tgz .:从当前目录创建压缩tar
tar -zxvf file.tgz .:从.tgz文件中解压文件
man:手册(man command)
zip file.zip file:将文件压缩为.zip文件
unzip file.zip:解压.zip文件


四、Ubuntu Linux系统管理

1.用户账户信息保存在/etc/passwd文件中

2.添加新用户可使用命令`sudo adduser username`

3.为确保用户能够使用sudo,需要在/etc/sudoers文件中添加一行:`username ALL(ALL)  ALL`

chapter2


一、Linux中的文件编辑器

1.vim编辑器

关于vim的使用可以在终端中使用vimtutor进行初学,半小时左右就能搞定教程,但是只花这半小时是无法精通vim编辑器的,因此还需要花时间多加练习才能熟练掌握。

2.gedit编辑器

gedit是Ubuntu及其他使用GNOME GUI用户界面的Linux的默认编辑器

3.emacs编辑器

最受欢迎的版本是GNU Emacs。

以上三款编辑器都支持直接输入和全屏模式下的文本编辑,还支持关键词搜索,可用新文本替换字符串。

二、程序开发需要学习的内容

程序开发步骤:

1. 创建源文件t1.c与t2.c
2. 用gcc把源文件转换成二进制可执行文件,如:gcc t1.c t2.c
简述流程为:
t.c-->-E(转换成汇编代码)-->t.s-->-S(转换成目标代码)-->t.o-->-c(链接)-->a.out
t1.c-->编译器-->t1.s-->汇编器-->t1.o-->链接器-->a.out
t2.c-->编译器-->t2.s-->汇编器-->t2.o-->链接器-->a.out
如果需要修改生成文件的命名,则需要添加参数-o

静态与动态链接

静态库的静态链接包含a.out所需的库函数代码和数据,而共享库的动态链接中,库函数并没有在a.out中。
动态链接的优点:
1.可减小每个a.out文件大小
2.许多可执行程序可在内存中共享相同的库函数
3.修改库函数不需要重新编译源文件
动态链接所用的库称为动态链接库(DLL),在Linux中称为共享库(.so)

可执行文件格式

1.二进制可执行平面文件
2.a.out可执行文件
3.ELF可执行文件

程序执行

在类Unix操作系统中,在sh命令行输入a.out one two three执行a.out文件,以标记字符串作为命令行参数。

程序终止:分正常终止和异常终止

32位GCC中C函数的调用

对函数可见的栈区称为函数栈帧,对于每个函数的调用,堆栈都会向低地址增加一个被调函数的帧,CPU的帧指针指向当前执行函数的栈帧,保存的FP指向其调用者的帧。

64位GCC中运行时堆栈使用情况

与32有一些不同,调用函数时,前六个参数依次进入rdi、rsi、rdx、rcx、r8、r9,其他任何参数通过堆栈。进入后先建立栈帧(rbp),肯呢个向下移动堆栈指针(rsp)。GCC编译生成的代码可保持堆栈指针固定不懂,默认保留红色区域堆栈128字节。

C语言程序与汇编代码链接

汇编代码说明
GCC生成汇编代码由三部分组成:
1.入口代码prolog
2.函数体代码
3.退出代码epilog
可以用汇编语言实现C函数,也能从汇编中调用C函数

链接库

假设有一个函数在mysum.c中,main函数在t.c中
创建静态链接库:
gcc -c mysum.c
ar rcs libmylib.a mysum.o
gcc -static t.c -L. -lmylib
a.out
创建动态链接库:
gcc -c -fPIC mysum.c
gcc -shared -o libmylib.so mysum.o
gcc t.c -L. -lmylib
export LD_LIBRARY_PATH=./
a.out

makefile

格式:一个make文件由一系列目标项、依赖项和规则组成
程序:make程序读取makefile时会比较依赖项列表中源文件的时间戳来确定要构建哪些目标项

makefile示例:
1.创建名为mk1的makefile
	myt:type.h t.c mysum.c 			#target:dependency list
			gcc -o myt t.c mysum.c	#rule:line MUST begin with a TAB
2.使用mk1作为makefile运行make
	make -f mk1
	make将构建目标文件myt并将命令显示为:gcc -o myt t.c mysum.c
3.再次运行make会出现:
	make: 'myt' is up to date
4.使用touch更改文件时间戳
	touch type.h
	make -f mk1
make将重新编译链接源文件,生成新的myt文件
5.删除依赖项列表中的一些文件名,即使这些文件有更改make也不会执行rule命令

makefile中的宏示例:
1.创建一个名为mk2的makefile
CC = gcc			#define CC as gcc
CFLAGS = -Wall		#define CFLAGS as flags to gcc
OBJS = t.o mysum.o	#define object code files
INCLUDE = -Ipath	#define path as an INCLUDE directory

myt:type.h $(OBJS)	#target:dependency:type.h and .o files
		$(CC) $(CFLAGS) -o t $(OBJS) $(INCLUDE)
在makefile中,宏定义的符号——$被替换为它们的值,但是还需要添加:
t.o:	 t.c type.h		#t.o depend on t.c and type.h
		gcc -c t.c
mysum.o: mysum.c type.h	#mysum.o depend type.h
		gcc -c mysum.c
2.以mk2作为makefile运行make
make -f mk2
3.运行生成二进制可执行文件myt

输入命令测试mk3:
1.make [all] -f mk3		#build all targets:myt and install
2.make install -f mk3	#build target myt and install myt
3.make run -f mk3		#run /usr/local/bin/myt
4.make clean -f mk3		#remove all listed files

makefile变量
自动变量:
1.$@:当前目标名
2.$<:第一个依赖项名
3.$^:所有依赖项名
4.$*:不包含扩展名的当前依赖项名
5.$?:比当前目标更新的依赖项列表
make还支持后缀规则,后缀规则并非目标,而是make程序的指令

GDB调试

在emacs IDE中使用GDB
	1.源代码:在X-window下打开一个伪终端,使用EMACS创建makefile
	t:t.c
		gcc -g -o t t.c
	2.编译源代码:打开EMACS的tools菜单,然后选择Compile,然后在编辑窗口底部显示make -k并等待响应
	3.启动GDB:打开tools菜单并选择Debugger,底部会显示gdb -i=mi t并等待响应,按enter键启动GDB调试工具
	4.设置断点调试:
		b main


		b sub
		b 10
多窗口GDB:在GDB菜单中选择Gud->GDB-MI->Display Other Windows

三、C语言相关

C语言程序中的常见错误

1.未初始化的指针或含有错误值的指针
2.数组下标越界
3.字符串指针和char数组使用不当
4.assert宏:可以确保指针不为NULL和数组大小不超过极限
5.在程序代码中使用fprintf()和getchar()

C语言结构体

基本结构:
struct node{
	struct node *next;
	int key;
	char name[64];
};
或
typedef struct node{
	struct node *next;
	int key;
	char name[64];
}NODE;
定义一个指针NODE x
对单个字段的访问为:
x.next
x.key
x.name
在运行时每个字段都作为相对于结构体起始地址的偏移量进行访问。

一个结构体的大小可以由sizeof(struct type)确定。
如果需要可以使用PACKED属性定义C结构体:
typedef struct node{
	struct node *next;
	int key;
	char name[2];
}__attribute__((packed, aligned(1))) NODE;
这种情况结构体大小为10字节,否则将自动填充为12字节。

使用库函数memncpy(&y,&x,sizeof(NODE))复制整个结构体。
联合体和结构体类似
union node{
	int *ptr;
	int ID;
	char name[32];
}x;
union的大小由最大的成员决定,在x中最大的为name32字节,因此x的大小为32字节。

C语言中指针是指向其他数据对象的变量(地址)。

C语言类型转换:
显式转换
隐式转换
常规数据类型与指针类型
需要使用转换运算符(TYPE)变量来实现

链表

可分为单向链表,双向链表等
操作:构建,遍历,搜索,插入,删除,重新排序

构建方法:使用数组(node[N])构建和使用堆区构建(node = (NODE *)malloc(N*sizeof(NODE));)

插入:头插法和尾插法

循环链表:尾节点指向头结点

可扩充结构体:包含不完全指定字段,必须要为实际结构体分配所需内存

双向链表:列表中元素按向前和向后两个方向链接

注意:在进行链表操作时应当注意链表结束的条件

树是由多级链表构成的动态数据结构
类型:二叉树,森林等

二叉搜索树的性质:
所有节点值不同;
节点左子树只包含值小于该节点值的节点;
节点右子树只包含值大于该节点值的节点;
左右子树也是二叉搜索树。

二叉搜索树的构建
二叉树遍历算法:先序遍历、中序遍历、后序遍历、深度优先遍历算法、广度优先遍历算法

引用转载请加上该链接:https://www.cnblogs.com/shibatori/p/17690176.html

posted @ 2023-09-09 21:24  シバ鳥  阅读(99)  评论(0)    收藏  举报