Shell
命令解释器,根据舒服的命令执行相应命令
查看当前系统下有哪些shell
1 | cat /etc/shells |
查看当前系统正在使用的shell
1 | echo $SHELL |
常见shell
1 | /bin/bash(就是linux的默认的shell) |
主键功能
功能 | 快捷键 | 助记 |
---|---|---|
Home | Ctrl-a | The first letter |
End | Ctrl-e | end |
Clear | Ctrl-u | Clear |
类Unix系统目录
1 | bin:存放二进制可执行文件 |
Linux系统文件类型
1 | 普通文件:- |
软链接:为保证软链接可以任意搬移,创建时务必对源文件使用绝对路径
硬链接:操作系统给每一个文件赋予唯一的inode,当有相同inode的文件存在时,彼此同步。删除时,只将硬链接计数减一。减为0时,inode被释放。
find
1 | -type 按文件类型搜索 |
压缩解压缩
1 | 压缩 |
1 | rar |
1 | zip |
vim基础操作
进入插入模式
1 | i:插入光标前一个字符 |
进入命令模式
1 | ESC:从插入模式或末行模式进入命令模式 |
GCC编译
- 预处理:展开宏、头文件,替换条件编译,删除注释、空白、空行
- 编译:检查语法规范(消耗时间、系统资源最多)
- 汇编:将汇编指令翻译成机器指令
- 链接:数据段合并,地址回填
1 | -I 指定头文件所在目录位置 |
静态库制作步骤
1 | gcc -c test.c -o test.o |
动态库制作步骤
1 | gcc -c test.c -o test.o -fPIC |
GDB调试
1 | -g 使用该参数编译可执行文件,得到调试表 |
其他指令
1 | run: 使用run查找段错误出现位置 |
makefile
命名:Makefile / makefile
1个规则
目标:依赖条件
- (一个tab缩进)命令
目标的时间必须晚于依赖条件的时间,否则,更新目标
依赖条件如果不存在,找寻新的规则去产生依赖
2个函数
src = $(wildcard ./*.c)
:匹配当前工作目录下的所有.c
文件,将文件名组成列表,赋值给变量src$(patsubst %.c,%.o,$(src))
:将参数3中,包含参数1的部分,替换为参数2
clean
: (没有依赖)
-rm -rf $(obj) a.out
:-
的作用是,删除不存在文件时,不报错,顺序执行结束。3个自动变量
$@
:在规则的命令中,表示规则中的目标$^
:在规则的命令中,表示所有依赖条件$<
:在规则的命令中,表示第一个依赖条件
模式规则
1
2.o:%.c
gcc -c $< -o %@静态模式规则
1
2(obj):%.o:%.c
gcc -c $< -o %@伪目标
1
.PHONY: clean ALL
参数
1
2-n : 模拟执行make、make clean命令
-f : 指定文件执行make命令
makefile实战
首先创建一个maketest
文件夹,该文件夹的目录结构如下图所示
inc
文件夹下head.h
代码如下
1 |
|
obj
文件夹下的文件是我们在编译时生成的。
src
文件夹下的hello.c
代码如下
1 |
|
1 | add.c |
接下来是编写makefile
文件,代码如下
1 | src = $(wildcard ./src/*.c) |
最后一步执行makefile
文件,在maketest
目录下,执行make
命令。就会在当前目录下生成a.out
文件,同时在obj
文件夹下也会生成相应的.o
文件。
制作特定的makefile管理文件,代码如下,将代码放在指定的目录下,可以对指定的.c
文件进行管理。执行命令的方式为make xxx
,即可使得xxx.c
文件通过gcc
编译之后输出为xxx
可执行目标文件。如果只执行make
指令,则会对当前目录下的所有.c
文件进行gcc
编译。
1 | src = $(wildcard *.c) |
函数相关
open函数
1 | int open(char *pathname,int flags) |
参数
1 | pathname:要打开的文件路径名 |
返回值
- 成功:打开文件所得到对应的文件描述符(整数)
- 失败:-1,设置error
1 | int open(char *pathname,int flags, mode_t mode) |
参数
1 | pathname:要打开的文件路径名 |
返回值
- 成功:打开文件所得到对应的文件描述符(整数)
- 失败:-1,设置errno
close函数
1 | int close(int fd) |
read函数
1 | ssize_t read(int fd,void *buf, size_t count); |
参数
1 | fd : 文件描述符 |
返回值
1 | 成功:读到的字节数 |
write函数
1 | ssize_t write(int fd,const void *buf, size_t count); |
参数
1 | fd : 文件描述符 |
返回值
1 | 成功:写入的字节数 |
错误处理函数
1 | printf("xxx error: %d\n",errno); |
fcntl
1 | int flgs = fcntl(fd,G_GETFL); |
read和write实现文件拷贝
1 |
|
lseek函数
1 | off_t lseek(int fd,off_t offset, int whence); |
参数
1 | fd: 文件描述符 |
返回值
1 | 成功:较起始位置偏移量 |
使用lseek函数读文件
1 |
|
lseek应用场景
文件的“读”、“写”使用同一偏移位置
使用lseek获取、拓展文件大小:要想使文件大小真正扩展,必须引起IO操作。
- 使用truncate函数直接扩展文件大小
1
2
3
4
5
6
7
8
9
10
11
12
13
int main(int argc, char *argv[])
{
int ret = truncate("lseek.txt",500);
printf("ret = %d\n",ret);
return 0;
}
使用lseek获取文件大小
1 |
|
1 | od -tcx filename 查看文件的16进制表示形式 |
传入参数
- 指针作为函数参数
- 通常有
const
关键字修饰 - 指针指向有效区域,在函数内部做读操作
传出参数
- 指针作为函数参数
- 在函数调用之前,指针指向的空间可以无意义,但必须有效
- 在函数内部,做写操作
- 函数调用结束后,充当函数返回值
传入传出参数
- 指针作为函数参数
- 在函数调用之前,指针指向的空间有实际意义
- 在函数内部,先做读操作,后做写操作
- 函数调用结束后,充当函数返回值
stat函数
1 | int stat(const char *path,struct stat *buf) |
参数
1 | path : 文件路径 |
返回值
1 | 成功:0 |
stat结构体
1 | struct stat { /* when _DARWIN_FEATURE_64_BIT_INODE is NOT defined */ |
stat函数获取文件大小
1 |
|
stat函数获取文件类型
1 |
|
stat和lstat的区别
stat会穿透符号链接,lstat不会。
unlink函数
1 |
|
unlink函数的特征:清除文件时,如果文件的硬链接数到0了,没有dentry对应,但该文件仍不会马上被释放,要等到所有打开该文件的进程关闭该文件,系统才会挑时间将该文件释放掉。
隐式回收
当进程结束运行时,所有该进程打开的文件会被关闭,申请的内存空间会被释放,系统的这一特性称之为隐式回收系统资源。
readlink函数
读取符号链接文件本身内容,得到链接所指向的文件名。
1 | ssize t readlink(const char *path,char *buf,size_t bufsiz); |
opendir
1 | DIR *opendir(const char *name) |
closedir
1 | int closedir(DIR *dirp) |
readdir
1 | struct dirent *readdir(DIR *dp) |
实现ls命令操作
1 |
|
递归遍历目录
直接贴代码
1 |
|
实现效果和linux原生大差不差
dup和dup2
1 | int dup(int oldfd); |
1 |
|
1 | int dup2(int oldfd,int newfd); |
1 |
|
fcntl函数实现dup
1 | int fcntl(int fd,int cmd,...) |