一、Linux常用命令
小技巧:
(1)ctrl + shift + = 放大终端窗口
(2)ctrl + - 缩小终端窗口
(3)自动补全:在敲出 文件 / 目录 / 命令 的前几个字母之后,按下 tab 键,如果输入的没有歧义,系统会自动补全;如果还存在其他 文件 / 目录 / 命令 ,再按一下 tab 键,系统会提示可能存在的命令
(一)、shell
Shell:命令解释器,根据输入的命令执行相应命令

(二)、目录和文件
1. 类Unix系统目录结构
Ubuntu没有盘符这个概念,只有一个根目录/,所有文件都在它下面
2.用户目录
位于/home/user,称之为用户工作目录或家目录
3.相对路径和绝对路径
从/目录开始描述的路径为绝对路径,从当前位置开始描述的路径为相对路径
4.目录内容(ls)
a 列出隐藏文件,文件中以”.”开头的均为隐藏文件,如:~/.bashrc
l 列出文件的详细信息
R 连同子目录中的内容一起列出

5.切换目录(cd)

6.查看命令路径(which)

7.查看路径(pwd)

8.创建目录(mkdir)



9.删除空目录,删除文件/目录(rmdir rm)

10.创建/修改文件时间(touch)
touch文件不存在创建新的,文件存在更新文件时间

11.重命名/移动文件(rm)
看第二个是否为已经存在的文件夹




12.拷贝文件/目录(cp)


13.查看文件内容(cat)

14.树形显示目录(tree)

15.查看目录大小

16.查看磁盘使用情况

(三)、文件属性和用户用户组
1.查看到当前登录用户(whoami)
可用于写入脚本

2.更改文件目录访问权限(chmod)
权值计算:可读权限r :4 , 可写权限w :2 , 可操作权限x :1 , 没有权限- :0
例如:rw-rw-r-- 权值0664
数字设定法 chmod 修改权限权值 文件名

3.更改文件目录或用户的组(chown)
sudo用于临时增加当前用户权限到root
sudo chown 用户:用户组 文件名

(四)、查找与检索
1.文件名查找(find)
find 指定路径 name ' '

2.内容检索(grep)
常用参数:-n:显示行号,-i:不区分大小写,-R:连同子目录一起查找
grep 参数 ‘ ’ 路径

(五)卸载安装软件
1.apt-get
更新源:sudo apt-get update
安装包:sudo apt-get install package
删除包:sudo apt-get remove
2.deb包安装
3.源码安装
(六)磁盘管理
文件系统类型:
(1)挂载



(2)卸载


(七)压缩包管理


(八)网络管理
(1)ifconfig

(2)ping

(3)netstat


(4)nslookup

(5)finger

(九)常见服务器构建
1.ftp
2.nfs
3.ssh
(十)其他命令
1.看手册man

2.清屏clear

3.设置指令别名alias
4.显示当前时间date

4.权限掩码umask

5.创建终端
创建终端标签:Ctrl+Shift+t
切换标签 Alt+n (n=1)
新开终端 ctrl+shift+n
(十一)进程管理
1.查看当前在线用户who
所有的选项都是可选的,不使用任何选项时,who命令将显示以下三项内容:
login name:登录用户名;
terminal line:使用终端设备;
login time:登录到系统时间;

2.监控后台进程ps


3.显示后台作业
ctrl z 挂起当前进程
第一列方括号中的数字表示作业序号,由当前运行的shell分配,而不是由操作系统统一分配的。在当前shell环境下,第一后台作业的作业号为1,第二作业的作业号为2…。第二列中的“+”号表示相应作业的优先级比“-”号对应作业的优先级高。第三列表明作业状态,是否为运行、中断、等待输入或停止等。最后列出的是创建当前这个作业所对应的命令行。

4.后台/挂起作业移到前台运行fg,挂起进程后台执行bg


5.进程发送信号
(1)查看信号编号

(2)既可以根据名字发送信号又可以根据编号发送

(3)大部分进程收到SIGTERM该信号就会终止,但是被挂起的进程不能处理信号,所以必须发SIGKILL信号,由系统强制终止进程。

6.查看当前进程环境遍历

(十二)、用户管理
1.创建用户

2.设置密码

3.切换用户

4.root用户 sudo su
5.删除用户


(十三)、关机重启
1.poweroff,shutdown 关机
2.reboot重启
(十四)、链接
链接有两种,一种被称为硬链接(Hard Link),另一种被称为符号链接(Symbolic Link).建立硬链接时,链接文件和被链接文件必须位于同一个文件系统中,并且不能建立指向目录的硬链接。而对符号链接,则不存在这个问题。默认情况下,ln产生硬链接。如果给ln命令加上-s选项,则建立符号链接。

二、vi&gcc&gdb
(一)vim
1.Vi有三种基本工作模式:命令模式,文本输入模式,末行模式

(1)命令模式进入插入模式
i: 插入光标前一个字符
I: 插入行首
a: 插入光标后一个字符
A: 插入行未
o: 向下新开一行,插入行首
O: 向上新开一行,插入行首
(2)插入模式或末行模式进入命令模式
ESC
(3)末行模式下
w:存盘
wq:存盘退出
q!:不存盘强制退出

2.Vim基础操作
(1)移动光标
gg: 光标移动文件开头
G: 光标移动到文件末尾
(2)删除命令
x: 删除光标后一个字符,相当于 Del
X: 删除光标前一个字符,相当于 Backspace
dd: 删除光标所在行,n dd 删除指定的行数
D: 删除光标后本行所有内容,包含光标所在字符
d0: 删除光标前本行所有内容,不包含光标所在字符
dw: 删除光标开始位置的字,包含光标所在字符
(3)撤销命令
u: 一步一步撤销
U: 一次性撤销当前行所作的所有操作
Ctr-r: 反撤销
(4)重复命令
. : 重复上一次操作的命令
(5)文本行移动:
>>: 文本行右移
<<: 文本行左移
(6)复制粘贴
yy: 复制当前行,n yy 复制 n 行
p: 在光标所在位置向下新开辟一行,粘贴
(7)查找命令
/: str查找
n: 下一个
N:上一个
(8)替换命令
把abc替换成123
:%s/abc/123/g
:%s/abc/123/gc(需用户确认)
(9)代码排版
gg=G: 代码自动缩进排版
3.Vim分屏操作
sp: 上下分屏,后可跟文件名
vsp: 左右分屏,后可跟文件名
Ctr+w+w: 在多个窗口切换

(二)、gcc
1.查看gcc版本号
-v / –v / –version 查看gcc版本号

2.-Wall 提示更多警告信息

3.-D 编译时定义宏,注意-D和之间没有空格

4.-g 包含调试信息 -On n=0∼3 编译优化,n越大优化得越多
(1)启动gdb


(2)GDB基本命令
run
(或简写r
):开始执行程序。break
(或简写b
):设置一个断点。例如,break main
会在主函数上设置一个断点。- delete 编号:删除断电
- disable :禁用断点,但不断删除它。
- enable :启用之前禁用的断点。
next
(或简写n
):执行下一行代码,但不进入函数内部。step
(或简写s
):执行下一行代码,如果是函数则进入函数内部。print
(或简写p
):打印变量的值。例如,print i
会打印变量i
的值。continue
(或简写c
):继续执行程序,直到下一个断点。quit
(或简写q
):退出GDB。list
(或简写l
):列出源代码。可以指定行号或函数名。info
:查看信息,比如info locals
查看局部变量,info breakpoints
查看所有断点。
三、makefile——项目管理工具
1.优点:
(1)可以使用便携的编译管理代码(不用每次都写复杂的编译命令)
(2)重用性极强,可以反复使用管理编译不同的工程
(3)节省编译时间
a.编译时间=(预处理+编译+汇编)(编译期,生成 .o文件)+链接(链接期,把所有.o文件和库文件链接生成可执行文件)
b.空间换时间:在第一次编译的时候不会节省编译时间,但会保存生成的中间 .o文件,在下一次编译的时候只需要重新编译修改的源文件,没有修改的源文件直接使用保存的 .o文件进行链接
c.如何识别哪个源文件被修改? 比较源文件的修改时间和.o文件的生成时间
2.注意
(1)mekefile文件必须以makefile或者Makefile命名
(2)使用#注释
(3)make命令执行makefile文件
(4)makefile脚本自顶向下建立依赖关系
(5)只会执行一个目标,如果需要多个目标,这些目标之间是主从关系
3.makefile三要素
(1)目标:完成编译生成可执行文件,目标一般为可执行文件的名字
(2)依赖:生成目标依赖文件和资源文件
(3)命令:根据依赖生成目标需要执行的命令
语法:
目标:依赖
(tba)命令


4.变量
(1)自定义变量
无需指定类型,默认都是字符串类型
变量名可以由大小写字母,数字,下划线构成,但不允许以数字开头
为了和高级语言区分开,一般使用全大写命名
使用变量$(变量名)
(2)特殊变量
$@:代表目标名
$^:代表当前所有依赖项
$<:代表依赖项中的第一项

5.函数和内建语法
(1)文件名处理函数
SRCFILE=$(wildcard *.c)
#使用该函数遍历当前文件夹下的所有文件,获取所有.c文件的名字,保存在SRCFILE中
(2)字符串处理函数
DSTFILE=$(patsubst %.c ,%.o,$(SRCFILE))
#使用该函数,把SRCFILE中保存的所有.c文件的名字替换成.o文件,替换完的结果保存在DSTFILE中
(3)内建语法
%.o : %.c
(tab)命令

6.常见变量
TARGET=myapp#存储目标文件名字
CC=gcc#存储编译命令
INCLUDE_PATH=../include#保存头文件路径
INSTALL_PATH=/user/bin#保存安装路径
LIBRARY_PATH=../library#保存库文件路径
CFLAGS=-I$(INCLUD_PATH) -c -g -Wall#编译选项
CPPFLAGS=-D#保存预处理选项

7.功能目标
与主目标不同,功能目标没有依赖 ,执行使用“make 功能目标名字“
(1)清除
clean:
(tab)rm -rf $(DSTFILE) $(TARGET)
(2)安装
install:
(tab)sudo cp $(TARGET) $(INSTALL_PATH)
(3)卸载
disclean:
(tab)sudo rm -rf $(INSTALL_PATH)/$(TARGET)
(4)打印
output:
(tab)echo $(INSTALL_PATH)/$(TARGET)

四、文件IO



1.文件描述符
一个进程默认打开3个文件描述符
STDIN_FILENO 0 标准输入
STDOUT_FILENO 1 标准输出
STDERR_FILENO 2 标准出错
新打开文件返回文件描述符表中未使用的最小文件描述符。
2.打开/关闭文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
(1)返回值:成功返回新分配的文件描述符,出错返回-1并设置errno
(2)flags参数
必选项:以下三个常数中必须指定一个,且仅允许指定一个。
* O_RDONLY 只读打开
* O_WRONLY 只写打开
* O_RDWR 可读可写打开
可选项
* O_APPEND 表示追加。如果文件已有内容,这次打开文件所写的数据附加到文件的末尾而不覆盖原来的内容。
* O_CREAT 若此文件不存在则创建它。使用此选项时需要提供第三个参数mode,表示该文件的访问权限。
* O_EXCL 如果同时指定了O_CREAT,并且文件已存在,则出错返回。
* O_TRUNC 如果文件已存在,并且以只写或可读可写方式打开,则将其长度截断(Trun-cate)为0字节。
#include <unistd.h>
int close(int fd);
返回值:成功返回0,出错返回-1并设置errno


3.最大文件个数
查看当前系统允许打开最大文件个数
cat /proc/sys/fs/file-max
当前默认设置最大打开文件个数1024
ulimit -a
修改默认设置最大打开文件个数为4096
ulimit -n 4096

4.read/write
read函数从打开的设备或文件中读取数据。
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
返回值:成功返回读取的字节数,出错返回-1并设置errno,如果在调read之前已到达文件末尾,则这次read返回0
write函数向打开的设备或文件中写数据。
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
返回值:成功返回写入的字节数,出错返回-1并设置errno


5.lseek


6.阻塞和非阻塞
读常规文件是不会阻塞的,不管读多少字节,read一定会在有限的时间内返回。
从终端设备或网络读则不一定,如果从终端输入的数据没有换行符,调用read读终端设备就会阻塞,如果网络上没有接收到数据包,调用read从网络读就会阻塞,至于会阻塞多长时间也是不确定的,如果一直没有数据到达就一直阻塞在那里。
同样,写常规文件是不会阻塞的,而向终端设备或网络写则不一定。
(1)阻塞读终端

(2)非阻塞读终端


五、Linux文件系统
一个磁盘可以划分成多个分区,每个分区必须先用格式化工具格式化成某种格式的文件系统,然后才能存储文件,格式化的过程会在磁盘上写 一些管理存储布局的信息。文件系统中存储的最小单位是块(Block)
一个块究竟多大是在格式化时确定的,可以设置为1024 2048 4096 默认4096——4KB IO块stat查看

启动块是由PC标准规定的,用来存储磁盘分区信息和启动信息,任何文件系统都不能使用启动块。启动块之后才是ext2文件系统的开始,ext2文件系统将整个分区划成若干个同样大小的块组(Block Group),每个块组都由以下部分组成。
超级块(Super Block) 描述整个分区的文件系统信息,例如块大小、文件系统版本号、上次mount的时间等等。超级块在每个块组的开头都有一份拷贝。
块组描述符表(GDT,Group Descriptor Table) 由很多块组描述符组成,整个分区分成多少个块组就对应有多少个块组描述符。每个块组描述符(Group Descriptor)存储一个块组的描述信息,和超级块类似,块组描述符表在每个块组的开头也都有一份拷贝,这些信息是非常重要的,一旦超级块意外损坏就会丢失整个分区的数据,一旦块组描述符意外损坏就会丢失整个块组的数据,因此它们都有多份拷贝。通常内核只用到第0个块组中的拷贝,当执行e2fsck检查文件系统一致性时,第0个块组中的超级块和块组描述符表就会拷贝到其它块组,这样当第0个块组的开头意外损坏时就可以用其它拷贝来恢复,从而减少损失。
块位图(Block Bitmap) 一个块组中的块是这样利用的:数据块存储所有文件的数据,比如某个分区的块大小是1024字节,某个文件是2049字节,那么就需要三个数据块来存,即使第三个块只存了一个字节也需要占用一个整块;超级块、块组描述符表、块位图、inode位图、inode表这几部分存储该块组的描述信息。块位图就是用来描述整个块组中哪些块已用哪些块空闲的,它本身占一个块,其中的每个bit代表本块组中的一个块,这个bit为 1表示该块已用,这个bit为0表示该块空闲可用。
为什么用df命令统计整个磁盘的已用空间非常快?
因为只需要查看每个块组的块位图即可,而不需要搜遍整个分区。相反,用du命令查看一个较大目录的已用空间就非常慢,因为不可避免地要搜遍整个目录的所有文件。
在格式化一个分区时究竟会划出多少个块组?
主要的限制在于块位图本身必须只占一个块。用mke2fs格式化时默认块大小是1024字节,可以用-b参数指定块大小,现在设块大小指定为b字节,那么一个块可以有8b个bit,这样大小的一个块位图就可以表示8b个块的占用情况,因此一个块组最多可以有8b个块,如果整个分区有s个块,那么就可以有s/(8b)个块组。格式化时可以用-g参数指定一个块组有多少个块,但是通常不需要手动指定,mke2fs工具会计算出最优的数值。
inode位图(inode Bitmap) 和块位图类似,本身占一个块,其中每个bit表示一个 inode是否空闲可用。
inode表(inode Table) ,一个文件除了数据需要存储之外,一些描述信息也需要存储,例如文件类型(常规、目录、符号链接等),权限,文件大小,创建/修改/访问时间等,也就是ls -l命令看到的那些信息,这些信息存在inode中而不是数据块中。每个文件都有一个inode,一个块组中的所有inode组成了inode表。
数据块(Data Block)根据不同的文件类型有以下几种情况 :对于常规文件,文件的数据存储在数据块中;对于目录,该目录下的所有文件名和目录名存储在数据块中,注意文件名保存在它所在目录的数据块中,除文件名之外,ls -l命令看到的其它信息都保存在该文件的inode中。注意这个概念:目录也是一种文件,是一种特殊类型的文件;对于符号链接,如果目标路径名较短则直接保存在inode中以便更快地查找,如果目标路径名较长则分配一个数据块来保存;设备文件、FIFO和socket等特殊文件没有数据块,设备文件的主设备号和次设备号保存在inode中。

1. 存储文件过程
(1)看BootBlock的磁盘分区
(2)看GDP块组描述表找到起始位置
(3)找空闲的inode节点,把文件属性存进去
(4)找到datablock先把文件内容存进去1
2. 读取文件过程
(1)通过BootBlock找到磁盘分区
(2)看GDP块组描述找到起始位置
(3)找inode table起始位置找到文件具体对应的inode节点,找到inode的节点标号,根据inode节点编号计算出inode的地址,根据inode的数据块指针周到 datablock中保存的文件内容
3. 删除文件过程
(1)BootBlock查看磁盘分区
(2)GDP块组描述符找到block bitmap和inode bitmap的起始位置
(3)inode bitmap 置0 blockbitmap 置0
4. 存储大文件

1.文件系统
(1)stat
stat既有命令也有同名函数,用来获取文件Inode里主要信息,stat 跟踪符号链 接,lstat不跟踪符号链接





(2)access
#include <unistd.h>
int access(const char *pathname, int mode);
按实际用户ID和实际组ID测试,跟踪符号链接
参数mode
R_OK 是否有读权限
W_OK 是否有写权限
X_OK 是否有执行权限
F_OK 测试一个文件是否存在
实际用户ID: 有效用户ID:sudo执行时,有效用户ID是root,实际用户ID是colin
(3)chmod
注意:函数
#include <sys/stat.h>
int chmod(const char *path, mode_t mode);
int fchmod(int fd, mode_t mode);


(4)chown
chown使用时必须拥有root权限。
#include <unistd.h>
int chown(const char *path, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group);
int lchown(const char *path, uid_t owner, gid_t group);
(5)utime
<utime.h>
头文件
int utime(const char *filename, const struct utimbuf *times);
filename
:指向文件名的指针,该文件的时间戳将被改变。times
:指向utimbuf
结构体的指针,该结构体包含了新的访问时间和修改时间。如果这个参数是NULL
,则文件的访问时间和修改时间会被设置为当前时间。
utimbuf
结构体的定义如下:
struct utimbuf {
time_t actime; // 访问时间
time_t modtime; // 修改时间
};
(6)truncate
#include <unistd.h>
#include <sys/types.h>
int truncate(const char *path, off_t length);
int ftruncate(int fd, off_t length);
(7)rename
文件重命名
#include <stdio.h>
int rename(const char *oldpath, const char *newpath);
(8)chdir
#include <unistd.h>
int chdir(const char *path);
int fchdir(int fd);
改变当前进程的工作目录
(9)getcwd
获取当前进程的工作目录
#include <unistd.h>
char *getcwd(char *buf, size_t size);
(10)pathconf
#include <unistd.h>
long fpathconf(int fd, int name);
long pathconf(char *path, int name);
(11)link
a.创建一个硬链接
当rm删除文件时,只是删除了目录下的记录项和把inode硬链接计数减1,当硬链接计数减为0时,才会真正的删除文件。
#include <unistd.h>
int link(const char *oldpath, const char *newpath);
硬链接通常要求位于同一文件系统中,POSIX允许夸文件系统
符号链接没有文件系统限制
通常不允许创建目录的硬链接,某些unix系统下超级用户可以创建目录的硬链
创建目录项以及增加硬链接计数应当是一个原子操作
b.创建符号链接
int symlink(const char *oldpath, const char *newpath)
c.读符号链接所指向的文件名字,不读文件内容
ssize_t readlink(const char *path, char *buf, size_t bufsiz)
d.int unlink(const char *pathname)
如果是符号链接,删除符号链接
如果是硬链接,硬链接数减1,当减为0时,释放数据块和inode,如果文件硬链接数为0,但有进程已打开该文件,并持有文件描述符,则等该进程关闭该文件时,kernel才真正 去删除该文件
利用该特性创建临时文件,先open或creat创建一个文件,马上unlink此文件
2.目录操作
(1)mkdir
#include <sys/stat.h>
#include <sys/types.h>
int mkdir(const char *pathname, mode_t mode);
(2)rmdir
#include <unistd.h>
int rmdir(const char *pathname);
(3)opendir/fdopenr
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
DIR *fdopendir(int fd);
(4)readdir
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
struct dirent {
ino_t d_ino; /* inode number */
off_t d_off; /* offset to the next dirent */
unsigned short d_reclen; /* length of this record */
unsigned char d_type; /* type of file; not supported by all file system types */
char d_name[256]; /* filename */
};
//readdir每次返回一条记录项,DIR*指针指向下一条记录项
(5)rewinddir
#include <sys/types.h>
#include <dirent.h>
void rewinddir(DIR *dirp);
//把目录指针恢复到目录的起始位置。
(6)telldir/seekdir
#include <dirent.h>
long telldir(DIR *dirp);
#include <dirent.h>
void seekdir(DIR *dirp, long offset);
(7)closedir
#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);
写ls文件





Comments NOTHING