学习笔记1

一、笔记
   第一章是书的引言部分,介绍了书的范围、Unix的历史、如何将Ubuntu Linux同时安装到Microsoft Windows中的virtual 虚拟机和VMware虚拟机上。还简单提到了unix/Linux常用命令、文件类型、文件系统组织等内容。我花了大概3小时来学习第一章,其中有很多内容比如虚拟机上的Linux、Linux命令等等,是我在大一时就接触到的,所有我很快就能回想起19年时在虚拟机上进行Linux编程的场景。但这本书上的内容更加深入、细致地谈到了Linux是怎样启动、工作的以及用户权限和安全性等问题。第一章的最后提到了sudo命令,我以前误以为sudo命令有启用超级用户的功能,直到看了书中17页的内容我才发现Ubuntu禁用了根或超级用户,sudo命令只是允许用户以超级用户的身份执行命令,执行完后用户进程将恢复到原来的级别。这明显是更加安全的。
   第二章首先介绍了几种Linux中的文本编辑器:vim、gedit、emacs。就我个人的使用体验而言,vim是功能最强大、可用性最好的一款。当然,刚开始接触vim时可能会有点不适应,但用着用着就会发现vim是真香。以下是我总结的用vim写c代码的步骤:
第一步: 在Linux桌面中键盘按 Ctrl + AIt + T 打开命令口终端
第二步: 输入命令 vi zjy.c 进入vi的命令行模式并创建一个文件名为“zjy.c” 的C文件
第三步: 输入命令 i (下方出现 --INSERT-- 的字符说明可以写C代码了)
第四步: 写C代码
第五步: 按 Esc 退出输入行模式,进入命令行模式(下方 --INSERT-- 消失)
第六步: 输入命令 :wq 退出并保存
第七步: 输入命令 ls 检查C文件是否创建并保存成功
第八步: 输入命令 gcc zjy.c -o zjy 编译zjy.c 文件并生成执行文件zjy
第九步: 输入命令 ./zjy 运行该文件

接着课本讲到了程序开发步骤:
(1)创建源文件
(2)用gcc把源文件转换成二进制可执行文件
c语言程序中的变量可分为全局变量、局部变量、静态变量、自动变量和寄存器变量。需要注意的是,全局变量在函数外定义。局部变量在函数内定义。全局变量具有唯一性,并且只有一个副本。静态全局变量仅对定义他们的文件可见。非静态全局变量则对同一程序的所有文件都可见。默认情况下,局部变量是自动变量,他们在函数调用时出现,按逻辑在函数退出时消失。静态局部变量具有永久性和唯一性。这是课本中总结得非常全面的。
(3)gcc是一个程序,它主要保护三个步骤:
第一步:将c源文件转换为汇编代码文件
xx.c —> xx.s
第二步:把汇编代码转换为目标代码(通常是二进制代码)。
xx.s -> xx.o
写到这时我脑海里突然灵光一闪,现代计算机有没有其他进制的代码?带着这个疑问我查阅了相关资料,其中比较有名的是前苏联制作的三进制计算机。二进制只有0和1两种状态,0代表假、1代表真。而三进制有-1、0、1三种状态,分别表示假、不确定、真。有了-1的存在计算机表示负数就更加简洁。当然这两者的区别还有很多,维基百科和一些视频资料还提到了三进制计算机比二进制计算机在AI领域有更好的发展前景,但其中涉及很多我不了解的知识,所以就没再深究。

第三步:链接
调用链接器,链接器将所有的.o文件和必要的库函数组合成单一的二进制可执行文件。

关于a.out:
我们都知道默认的二进制可执行文件名为a.out,但对其内容几乎没有了解。书中第页讲到,a.out的内容包括4个部分:
(1)文件头:包含a.out文件的加载信息和大小
(2)代码段:也叫正文段,代码段从标准c启动代码crt0.o开始
(3)数据段
(4)符号表
程序终止:
我们可通过两种方法来终止正在执行a.out的进程
1、正常终止:如果程序执行成功,main最终会返回到crt0.o调用库函数exit(0)来终止进程。
2、异常终止:进程遇到错误时,按下“ctrl+c”或使用命令:
Kill - s signal_number pid

第二章的后半部分讲到了c语言结构体、链表处理、树二叉树等内容,这些知识点在大二上的《数据结构》课程中都细讲过。我浏览了两遍,基本上都是我已经掌握的内容,少数遗忘的部分我也很快就回想起来。

二、知识点归纳以及自己最有收获的内容
知识点:
(1)unix/linux常用命令
ls:ls dirname:列出CWD或目录的内容
cd dirname:更改目录
pwd:打印CWD的绝对路径名
touch filename:更改文件名时间截
cat filename:显示文件内容
cp src dest:复制文件
mv src dest:移动或重命名文件
mkdir dirname:创建目录
rmdir dirname:移除目录
In oldfile newfile:在文件之间创建链接
find:搜索文件
grep:搜索文件中包含模式的行
ssh:登录到远程主机、
gzip filename:将文件压缩为.gz文件
gunzip file.gz:解压.gz文件
tar -zcvf file.tgz:从当前目录创建压缩tar文件
tar -zxvf file.提供者:从.tgz文件中解压文件
man:显示在线手册

(2)Sudo命令:
执行命令时临时将用户进程提升到超级用户级别。完成命令执行后,用户进程将恢复到原来的特权级别。

(3)Vim的3中操作模式:
命令模式:用于输入命令
插入模式:用于输入和编辑文本
末行模式:用于保存文件并退出

(4)a.out文件内容
文件头:包含a.out文件的加载信息和大小
代码段:包含程序的可执行代码
数据段:包含初始化全局变量和初始化静态数据
符号表:仅为运行调试所需

(5)c语言结构体
c语言结构体类型由struct关键字定义。
Next:指向下一个节点结构体的指针
Key:一个整数
Name:一个由64个字符组成的数组
此类结构体可定义为:
Sruct node{
Struct node *next:
Int key:
Char name[64]:
}
Struct node可作派生类型来定义该类型的变量。
注:定义c语言结构体时,该结构体的每个字段都必须具有一个编译器已知的类型,但自引用指针除外。一个结构体的大小可以由sizeof(struct type)确定。

(6)链表
Typedef struct node{
Struct node *next;
Int value;
Char name[];
}NODE;
链表是一种由一系列节点组成的数据结构,这些节点通过节点的next指针链接在一起,即每一个节点的next指针指向列表中的下一个节点。

(7)树和二叉树
最简单的树是二叉树,其每个节点都有两个指针,分别是左指针和右指针。
Typedef sruct node{
Int key;
Struct node *left;
Struct node *right;
}NODE;
二叉树的遍历算法:
先序遍历:node;node.left;node.right
中序遍历:node.left;node;node.right
后序遍历:node.left;node.right.node
深度优先(DF)
广度优先(BF)

最有收获的内容:
  这两章我最有收获的内容是Linux的文件系统组织。以前在编写完程序后,文件夹里会出现命名为bin、lib、dev等的文件夹,我并不知道这些文件夹是干什么的?有什么作用?他们的内容是什么?而书中的15页讲到了这一块,让我清楚不同的文件夹的的内容。例如bin(普通用户命令)、dev(设备文件)、lib(链接库)、sbin(超级用户命令)。文件类型分为目录文件和非目录文件。另外我还了解到超级用户命令的启用方法、过程,这让我对Linux文件系统、编程过程有了更加深入的了解。

·创建一个文件的过程:
在命令行输入命令:
$ who > userlist
当完成这个命令时,文件系统中增加了一个存放命令who输出内容的新文件userlist。
文件主要有属性、内容以及文件名三项。内核将文件内容存放在数据区,文件属性存放在i-节点,文件名存放在目录中。
创建成功一个文件主要有以下四个步骤:
1、存储属性
也就是文件属性的存储,内核先找到一块空的i-节点。例如,内核找到i-节点号921130。内核把文件的信息记录其中。如文件的大小、文件所有者、和创建时间等。
2、存储数据
即文件内容的存储,由于该文件需要3个数据块。因此内核从自由块的列表中找到3个自由块。如600、200、992,内核缓冲区的第一块数据复制到块600,第二和第三分别复制到922和600.
3、记录分配情况
数据保存到了三个数据块中,所以必须要记录起来,以后再找到正确的数据。分配情况记录在文件的i-节点中的磁盘序号列表里,这3个编号分别放在最开始的3个位置。
4、添加文件名到目录
新文件的名字是userlist 内核将文件的入口(47,userlist)添加到目录文件里。文件名和i-节点号之间的对应关系将文件名和文件和文件的内容属性连接起来,找到文件名就找到文件的i-节点号,通过i-节点号就能找到文件的属性和内容。

3、问题与解决思路
问题1:为什么Linux系统没有windows那种直观、高效的面向对象的图形用户界面,却深受程序开发者的喜欢?
解决思路:因为我最早接触的系统是Windows,所以觉得Windows系统这种面向对象的用户界面和开发环境模拟了现实世界的行为,已于学习、理解和使用。就现在来看,我对Linux系统的接触还不够深入,但我已经逐渐体会到了Linux系统在软件支持、开源、安全性上的优势。所以要回答这个问题,我可以考虑请教一些有经验的程序员,问他们使用不同系统的编程感受,但我想,随着我对Linux的深入使用,我会慢慢有答案。

问题2:windows中可以使用任务管理器来查看当前的用户进程,并进行暂停、终止等操作。Linux系统也有类似任务管理器的功能吗?如何使用?
解决思路:通过查阅相关资料,我找到了linux 查看任务管理器,LINUX查看进程的4种方法。
第一种:
ps aux

ps命令用于报告当前系统的进程状态。可以搭配kill指令随时中断、删除不必要的程序。ps命令是最基本同时也是非常强大的进程查看命令,使用该命令可以确定有哪些进程正在运行和运行的状态、进程是否结束、进程有没有僵死、哪些进程占用了过多的资源等等,总之大部分信息都是可以通过执行该命令得到的。

a:显示当前终端下的所有进程信息,包括其他用户的进程。

u:使用以用户为主的格式输出进程信息。

x:显示当前用户在所有终端下的进程。

第二种:
ps -elf

-e:显示系统

-l:使用长(long)格式显示进程信息。

-f:使用完整

第三种:
top

以全屏交互式的界面显示进程排名,及时跟踪包括CPU、内存等系统资源占用情况,默认情况下每三秒刷新一次,其作用基编程客栈本类似于Windows系统中的任务管理器。

Tasks(系统任务)信息:total,总进程数;running,正在运行的进程数;sleeping,休眠的进程数;stopped,中止的进程数;zombie,www.cppcns.com僵死无响应的进程数。

CPU信息:us,用户占用;sy,内核占用;ni,优先级调度占用;id,空闲CPU;wa,I/O等待占用;hi,硬件中断占用;si,软件中断占用;st,虚拟化占用。了解空闲的CPU百分比,主要看%id部分。

Mem(内存)信息:total,总内存空间;used,已用内存;free,空闲内存;buffers,缓存区域。

Swap(交换空间)信息:total,总交换空间;used,已用交换空间;free,空闲交换空间;cached,缓存空间。

第四种:
pstree -aup

以树状图的方式展现进程之间的派生关系,显示效果比较直观。

-a:显示每个程序的完整指令,包含路径,参数或是常驻服务的标示;

-c:不使用精简标示编程客栈法;

-G:使用VT100终端机的列绘图字符;

-h:列出树状图时,特别标明现在执行的程序;

-H:此参数的效果和指定"-h"参数类似,但特别标明指定的程序;

-l:采用长列格式显示树状图;

-n:用程序识别码排序。预设是以程序名称来排序;

-p:显示程序识别码;

-u:显示用户名称;

问题3:为什么在某些环境中 who am i 和 who mom likes 命令不会输出任何内容?
解决思路:这个问题我问了几位同学,目前还没有得到确定的回答。我在思考会不会是当前使用的用户和登录时的用户不一样导致的。

问题4:Linux下如何获取root权限?
解决思路:开始我以为第一次创建的用户就是root用户,直到我发现部分命令不能正确执行。然后我通过百度搜索到几种方法:在命令前目加上sudo,这是一种非永久性获取root权限的方法,仅对这行命令有效。或者在终端输入sudo su,以root身份登陆到终端,

四、实践内容
(1)使用Linux编程
1、输入命令 vi zjy.c 进入vi的命令行模式并创建一个文件名为“zjy.c” 的C文件。
2、输入命令i,开始编写代码。

3、按 Esc 退出输入行模式,进入命令行模式(下方 --INSERT-- 消失)。
4、输入:wq退出并保存。
5、输入命令 ls 检查C文件是否创建并保存成功

6、输入命令 gcc zjy.c -o zjy 编译zjy.c 文件并生成执行文件zjy
7、输入:./zjy,执行程序

(2)tree指令

(3)file命令:查看文件格式
Od命令:od - tc -tx4 +文件名

posted @ 2021-09-14 12:06  20191223张俊怡  阅读(47)  评论(0编辑  收藏  举报