2、编写总控Makefile(定义预定义变量 or 自定以变量)... 55
3、进入src编写Makefile(将所有的.c文件生成.o文件并移动到obj目录中) 55
4、 进入obj编写Makefile(将所有的.o文件生成了可执行文件并移动到bin目录中) 55
一、linux简介
1.linux发展史
2.linux的发行版本
3.shell
shell、shell命令、shell脚本的本质区别:
shell:负责完成用户和内核之间的交互
shell是一个命令行解释器,将用户命令解析为操作系统所能够识别的指令,从而实现用户与操作系统的交互。
shell命令:是用户向系统内核发出控制请求,与之交互的一个文本流。
shell脚本:一堆命令的集合。
3.1shell命令
命令 [选项] [参数]
注意:[]表示可以省略
选项:功能
参数:要操作的对象
注意:
- 一条命令的三要素之间用空格隔开
- 若将多个命令写在一行,用分号隔开
- 如果一条命令不能在一行写完,在行尾使用反斜杠(\)标明该命令未结束
3.2shell类型
Shell类型
Bourne Shell: 最早的Shell
C Shell
Ksh
Z Shell
Bourne-again shell(bash)
二、linux的基本命令
(一)Linx用户管理
(1)相关的配置文件
(1)/etc/passwd 系统能够识别的用户清单
(2)/etc/shadow 加密的用户清单
(3)/etc/group 包含了UNIX组的名称和每个组中的成员列表
(2)创建用户
vim /etc/passwd
sudo adduser 用户名
注意:删除的时候连同用户的主目录一起删除
sudo deluser --remove-home 用户名
sudo groupadd 组名
vim /etc/group 查看组名
sudo usermod -g 目标组 要修改的用户
sudo groupdel 组名
(3)用户系统相关命令
方式1:
su – 用户名 <==> su –
方式2:
su root
注意:路径不会发生改变
top:动态显示系统中运行的程序
ps:显示当前系统中该用户运行的进程列表
ps -ef:查看所有进程及PID(进程号)
ps -aux:除了-ef显示的内容外,还可显示cpu及内存占用率、进程状态
pstree:进程树
kill:输出指定的信号给指定的(PID)进程
kill-l:列出所有可用的信号名称
free:查看当前系统内存的使用情况(磁盘空间还剩下多少)
df:查看文件系统的磁盘空间占用情况
du:统计目录或者文件所占磁盘空间的大小
fdisk-l:列出文件系统的分区情况
LinuxOS下7种文件类型:
- 普通文件 -
- 目录文件 d
- 字符设备文件 c
- 块设备文件 b
- 管道文件 p
- 链接文件 l
- 套接字文件 socket(s)
1.4.1chmod(change mode)
作用:改变文件的访问权限
注意:第一个字母表示的是文件类型
-rw-rw-r-- 1 linux linux 102 1 月 1 18:18 demol.c
- rw- rw- r--
文件类型 文件拥有者 文件属组用户 其他人
方式1:
文件拥有者 u
所属的用户组 g
系统里的其他用户 o
所有人 a
r 读 w 写 x 运行
+:表示增加权限
-:表示删除权限
=:表示设置权限
方式2:
注意:有权限用1表示,-表示没有权限,用0表示
案例:rwx -w- --x 111 010 001
1.4.2chown(change owner更改拥有者)
注意:chown使用的时候必须使用root权限
作用:修改文件所有者和组别
修改所有者:
修改组别:
同时修改:
作用:修改组别
注意:使用的时候必须使用root权限
grep 字符串 文件
作用:从指定的的文件中查找特定的字符串
-n:显示行号
作用:起别名
注意:
- 一次性的,只对当前终端有效
- 想要永久生效,添加进.bashrc
find[路径][选项][描述]
-name:根据名字搜索
(二)特殊字符
``反引号 将其当作命令处理
|:管道(一般不单独使用)
作用:将前一个命令的输出作为后一个命令的输入
cat:适合查看比较短的文档(一次性全部显示)
more:适合查看比较长的文档(按回车向下翻一行,空格向下翻一页,按q退出)
less:加强版的more,适合查看比较长的文档(按回车向下翻一行,空格向下翻一页,按q退出,支持上下箭头)
sudu shutdown -h now//立刻关机
sudu shutdown -h +10//十分钟后关机
sudu reboot//重启
通配符:
*:匹配任意长度的字符
?:匹配一个长度的字符串
如果是??就是两个字符长度的字符串,以此类推
[]:匹配其中指定的一个字符
[-]:匹配指定的一个字符范围
[^…]:除了其中指定的字符外的,均可匹配(一个字符范围)
注意:除了*和?,其他均是匹配一个字符
输入输出重定向:
>:输出重定向,如果文件不存在新建,如果文件存在则清空文件内容
>>:追加重定向,如果文件不存在则新建,如果文件存在则追加在文件的末尾
wc-c:统计文件有多少个字符
wc-l:统计文件有多少行
2>或&>:将错误信息输入到指定的文件中
(三)硬链接和软链接
硬链接:利用linux中为每个文件分配的物理编号—inode建立链接
软链接:利用文件的路径名建立链接
创建硬链接:
创建软链接:
区别
- 注意:软链接会在用户选定的位置生成一个文件的镜像,不会重复占用磁盘空间,平时使用最多的就是软链接
- 硬链接会在用户选定的位置上生成一个和源文件大小相同的文件
共同点:
无论是软链接还是硬链接都会保持同步性,不论修改哪一处,其他文件都会发生相同的变化,
删除源文件后,硬链接还存在,软链接内容也被删除
(四)压缩打包相关命令
压缩工具:
gzip、bzip2
注意:gzip、bzip2只能压缩文件
压缩:
gzip 文件名,后缀为.gz
bzip2 文件名,后缀为.bz2
解压:
方式1:
gzip -d 文件名
bzip2 -d 文件名
方式2:
gunzip 文件名
bunzip2 文件名
tar:对文件目录进行打包或解包,后缀为.tar
-c:打包
-x:解包
-v:显示详细过程
-f:指定包文件名(该参数必须放在最后)
-z:调用gzip或者gunzip
-j:调用bzip2或者bunzip2
先打包,再压缩
打包:
压缩:
先解压再解包
解压:
解包:
将打包压缩一体化:
将解压解包一体化:
(五)linux软件管理
安装软件包:
- sudo apt-get update
- sudo apt-get install 包名
卸载:
sudo apt-get remove 包名
(六)、linux的环境变量
env:查看所有的环境变量
为什么再所有的路径下都能认识ls?
Linux系统中环境变量的格式:环境变量名=内容1:内容2
环境变量名一般大写,如果有多个内容用冒号隔开。有一点需要注意的是,“=”号两边不能有空格。
查看环境变量的内容可以使用命令“echo $环境变量名”,如查看环境变量PATH的内容,使用echo $PATH。
添加环境变量使用命令export,分为临时添加和永久添加。
(一)临时添加
(二)永久添加
1.sudo vim /etc/profile(vim后面有一个空格)
2.在文件末尾添加:expor PATH=$PATH:/home/linux/22121/day2(要添加的路径)
3.source/etc/profile 或者 重启(更保险)
四、共享文件
(一)虚拟机-->设置-->选项-->共享文件夹
注意:共享文件夹在/mnt/hgfs
(二)(ifconfig)查看ip地址
注意:使用上述方法必须开启ssh服务
测试网络是否有网
- 虚拟机——>设置——>网络适配器
(二)编辑-->虚拟网络编辑器
设置静态IP:
Linux下:
window下:
(一)网络基础知识
(1)ip地址
ip地址是主机的唯一标识
ip地址的组成:网络地址和主机地址
根据网络地址的不同可以分为A、B、C、D、E
A类地址:1个字节的网络地址+ 3个字节的主机地址,网络地址的最高位必须是0
地址范围:1.0.0.0 ~ 126.255.255.255
B类地址:2个字节的网络地址 + 2个字节的主机地址,网络地址的最高位必须是10
地址范围:128.0.0.0 ~ 191.255.255.255
C类地址:3字节的网络地址 + 1字节的主机地址,网络地址的最高位必须是110
地址范围:192.0.0.0 ~ 223.255.255.255
D类地址
E类地址
(2)子网掩码
作用:判断主机发送的数据包是向外网发送还是向内网发送
网络地址全是1,主机地址全是0
1111 1111 1111 1111 1111 1111 0000 0000
255 255 255 0
192.168.4.70 192.168.4.110 192.168.1.23
& 255.255.255.0
192.168.4.0 192.168.4.0 192.168.1.0
(3)网关
如果想要向外网发送数据,就必须经过网关
(4)DNS服务器
DNS服务器:解析器 + 域名服务器组成的
注意:域名必须对应一个ip地址,而ip地址不一定有域名
将域名映射为ip地址的过程称为域名解析
六、shell脚本
C语言:编译性语言,强类型语言(对数据类型区分的很清楚)
shell脚本:解释性语言(不需要编译),弱类型语言(不区分数据类型)
shell脚本:一堆命令的集合
(1)touch 1.sh
(2)编辑 vim 1.sh
- 执行的时候没有权限,需要人为的去添加
chmod 777 1.sh
- 运行
./1.sh
(二)shell变量
(1)自定义变量
shell允许用户建立,变量存储类型,它不支持数据类型
注意:任何赋值给变量的值都被shell解释为一串字符。
命名规范:
- 由数字、字母下划线组成,且首字母不能为数字
- shell中变量通常用大写标识
注意:
- 要取用变量的值,只需要在变量前面加一个$
- 等号的左右两侧不能有空格
(2)位置参数
(3)预定义变量
$#:包含命令行参数的个数
$@:包含所有命令行参数
$*:包含所有命令行参数
$?:包含前一个命令的退出状态,正常退出返回0,反之返回非0(shell0为真,非0为假)
$$:包含正在执行的ID号
(4)环境变量
案例:在用户的主目录下创建一个mydir的文件夹,在该文件夹中创建一个1.txt,然后向1.txt中写入”hello shell”
(三)shell程序和语句
(1)说明性语句
#:标识注释
(2)功能性语句
输出:
echo 自带换行
不换行:添加-n参数
输入:
read 变量
想要添加提示语:添加-p参数
注意:双引号后面必须添加空格
想要换行:
如果想要NUM1输出”hello shell”,NUM2输出”22121”
expr主要用于简单的整数运算,包括加(+)、减(-)、乘(\*)、整除(/)和求模(%)
注意:expr与变量以及变量与运算符之间必须加空格
测试字符串、整数、文件属性
2.1 字符串测试
s1 = s2 测试两个字符串的内容是否一致
s1 != s2 测试两个字符串的内容是否不一致
-z s1 测试s1 字符串的长度是否为0
-n s1 测试s1 字符串的长度是否不为0
注意:”[“的右侧以及 “]”的左侧必须有空格
2.2 测试整数
a -eq b 测试a与b是否相等
a -ne b 测试a与b是否不相等
a -gt b 测试a是否大于b
a -ge b 测试a是否大于等于b
a -lt b 测试a是否小于b
a -le b 测试a是否小于等于b
2.3 测试文件属性
-e name 测试name是否存在
-d name 测试name 是否为一个目录
-f name 测试name 是否为普通文件
-L name 测试name 是否为符号链接
-r name 测试name 文件是否存在且为可读
-w name 测试name 文件是否存在且为可写
-x name 测试name 文件是否存在且为可执行
-s name 测试name 文件是否存在且其长度不为0
f1 -nt f2 测试文件f1 是否比文件f2 更新
f1 -ot f2 测试文件f1 是否比文件f2 更旧
(3)控制语句
(1)单分支选择语句
if [ 表达式 ]
then
语句
fi
(2)双分支选择
if [ 表达式 ]
then
语句1
else
语句2
fi
多分支选择
if [表达式1]
then
语句1
elif[表达式2]
then
语句2
....
elif [表达式n]
then
语句n
else
语句n+1
fi
case 字符串变量 in
模式1)
语句1
;;
模式2)
语句2
;;
.....
模式n)
语句n
;;
*)
语句n + 1
;;
esac
注意:最后一个双分号可以省略,其它不能省略
案例1:
输入一个文件,判断它是否为普通文件,如果是普通文件,判断它是否有写的权限
如果有写的权限,向文件中写入hello shell
如果没有写的权限,给它添加写的权限,写入hello shell
案例2:
请输入你想下载文件的名字,让用户确认,
用户输入是否下载这个软件,[Y/N/Q],Y:正在下载 N:用户取消下载 Q:退出
for 变量 in 单词表
do
语句
done
方式1:
方式2:
注意:单词表中不能为变量
方式3:
方式4:
方式5:
案例:打印9*9乘法表
while [表达式]
do
语句
done
break:跳出循环
continue:结束本次循环,开始下一次循环
七、函数
(一)函数的定义
方式1:
函数名()
{
}
方式2:
function 函数名()
{
}
注意:使用最多的是方式2
(二)函数的调用
方式1:
变量=`函数名 参数列表`
方式2:
函数名 参数列表
注意:平时使用最多的是方式2
注意:函数的所有标准输出都传递给了主程序的变量
注意:函数中的$n并不是脚本中的$n
案例:
(三)main函数传参
(四)malloc函数
头文件:
#include <stdlib.h>
函数原型:
void *malloc(size_t size);
函数功能:申请内存空间
参数:要申请的空间的大小
返回值:成功返回申请到的空间的首地址,失败返回NULL
注意:
- malloc申请到的空间是没有名字
- malloc申请到的空间是一片连续的内存空间
案例:描述一个学生的姓名、年龄、三门成绩
#define M 20
#define N 3
#define SIZE 3
typedef struct student
{
char name[M];//姓名
int age;//年龄
float scores[N]
}Stu;
//申请SIZE个Stu这么大的空间
(五)memset函数
头文件:#include<string.h>
函数原型:
void *memset(void *s, int c, size_t n);
函数功能:重置内存空间
参数1:要重置内存空间的首地址
参数2:要重置的值
参数3:要重置的内存空间的大小
(六)free
void free(void *ptr);
函数功能:释放空间
参数:要释放的空间的首地址
八、goto语句
无条件语句
goto 语句标号;
注意:语句标号符合标识符的命名规范
九、位运算
&、|、~、^、<<、>>、
2.1 按位与
1101 0010
& 0101 1011
0101 0010
案例:将1101 0111 的0~2位清零
1101 0111
& 1111 1000
1101 0000
2.2 按位或
1101 0011
| 0110 1101
1111 1111
案例:将1101 0111的0~2位变成010(先清零,再赋值)
1101 0111
& 1111 1000
-------------------------
1101 0000
| 0000 0010
1101 0010
2.3 取反
~1101 0011 ---> 0010 1100
2.4 异或
相同为0,不同为1
1100 0111
^ 1001 1010
0101 1101
2.5 左移
高位丢弃,低位补0
案例:将2左移两位
0000 0010 -> 0000 1000
2.6 右移
无符号数:低位丢弃,高位补0
有符号数:低位丢弃,高位补1
十、结构体
(一)概念
描述一类事物相关属性的集合,是一种自定义的数据类型
(二)定义
struct 结构体名
{
属性1;
属性2;
....
属性n;
};
//描述一个人的姓名,年龄
struct people
{
char name[20];//姓名
int age;//年龄
};
//定义了一个结构体,结构体的数据类型为struct people
(三)定义一个结构体变量
存储类型 数据类型 变量名;
int a;//定义了一个整型变量
数据类型 *指针变量名;
int *p;//定义了一个指针变量
数据类型 结构体变量名;
struct people per = {0};
(四)初始化
struct 结构体名 结构体变量 = {...............};
(五)访问
(1)通过结构体变量访问
变量名.成员
(2)通过结构体指针变量访问
指针变量名->成员;
数据类型 *指针变量名;
定义一个指向整型变量的指针:int *p = &a;
定义一个指向数组的指针:int (*p)[3] = NULL;
定义一个指向结构体的指针:
struct people *p = NULL;
(六)字节对齐
自然对齐方式(32OS)
char:1字节对齐
short:2字节对齐
int:4字节对齐
float:4字节对齐
double:4字节对齐方式,分配的时候按4字节对齐分配,分配两次
注意:选成员中最大的那个对齐
(七)节省结构体空间的办法
(1)将数据类型最大的放到最前面
(2)位域或者位段
未优化之前:
优化之后:
注意:位域不能使用标准输入进行输入
可以进行赋值:
作业:
- 描述一个学生的姓名,年龄、三门成绩(float)、对它进行输入、输出
(八)给结构体起别名
方式1:
方式2:
.h文件
“”:从用户的工作路径去搜索头文件
<>:从用户的标准库路径去搜索头文件 /usr/include
作用:防止头文件重复定义
#ifndef 标号(一般用大写标识,将所有的.换成_)
#define 标号
#endif
程序的编译要经历预处理、编译、汇编、链接四个阶段
- 第一种方式
预处理:gcc -E test.c -o test.i //处理以#开头的文件
编译:gcc -S test.i -o test.s //生成汇编语言
汇编:gcc -c test.s -o test.o //将汇编语言转换成机器语言
链接:gcc test.o -o test //与其它的机器代码文件和库文件汇集成一个可执行的二进制代码文件
- 第二种方式
将gcc的前四个阶段合四为一
gcc main.c -o main
- 将gcc的前三个阶段合三为一
- 将所有的.o文件汇集生成一个可执行文件
make命令会在用户工作路径下找一个叫做Makefile/makefile(M大写小写都可以)的文件
3.1 Makefile命名规范
目标文件1:依赖文件1
(Tab键)依赖文件1是如何生成目标文件1
目标文件2:依赖文件2
(Tab键)依赖文件2是如何生成目标文件2
注意:
- 一个Makefile中可以有多个目标文件
- 如果两个目标文件之间没有依赖关系,执行make命令时,系统默认执行目标1
- 调用make命令时需要指明目标文件是谁,如果没有指定,默认执行目标文件1
3.2 假目标
解决假目标的办法:
在目标文件前面加上.PHONY(必须是大写)
3.3 预定义变量
CC:编译器的名称,默认为cc
CFLAGS:编译器的选项,无默认值
RM:文件删除程序的名称,默认为rm -f
3.4 自定义变量
OBJ和OBJS,一个用于存放可执行文件,一个用于存放的目标文件
3.5 自动变量
$@:表示目标文件
$<:表示第一个依赖文件
$^:表示所有的依赖文件
3.6 定义变量的两种方式
3.6.1 递归展开方式 VAR=var
注意:后面的变量会影响前面的结果
3.6.2 简单方式
3.7 嵌套Makefile
1、创建文件夹
bin(可执行文件)、include(.h文件)、src(*.c文件)、obj(*.o文件)
2、编写总控Makefile(定义预定义变量 or 自定以变量)
3、进入src编写Makefile(将所有的.c文件生成.o文件并移动到obj目录中)
4.进入obj编写Makefile(将所有的.o文件生成了可执行文件并移动到bin目录中)
5.再次编写总控Makefile(制定执行规则)
4、枚举
作用:使程序变得更加语义化
#define INPUT 1
#define OUTPUT 2
#define CALPMAX 3
#define SORT 4
5、共用体
特点:所有成员的首地址都是一样的(空间的大小由成员中最大的那个决定)
判断是大端序还是小端序:
制定规则,自己调用自己
5!
5 * 4! return 120
4 * 3! return 24
3 * 2! return 6
2 * 1! return 2
1 return 1
求斐波那契数列的前10项
1 1 2 3 5 8 13 21
定义一个指向整型的指针:int *p;
定义一个指向整型指针的指针:int **p;
定义一个指向数组的指针:int (*p)[5];
定义一个指向结构体的指针:Stu *p;
定义一个指向函数的指针:
int sum(int m,int n);//数据类型:int (int , int)
int (*p)(int,int);
定义一个函数指针数组,该数组有3个元素,每一个元素都是函数指针,该函数的返回值为int,有两个int型的参数
int (*p[3])(int,int);
返回值为指针的函数