课程安排
1天半:LinuxOS
1天:shell编程
3天:C高级(结构体、共用体、枚举、函数指针、指针函数、多文件编译、make工程管理)
day1
- 结构体
- 概念
是一类相关事物属性的集合,是一种自定义的数据类型
1.2 定义
struct 结构体名
{
属性1;
属性2;
....
属性n;
};
//描述一个人的姓名,年龄
struct people
{
char name[20];//姓名
int age;//年龄
};
定义了一个结构体,结构体的数据类型为struct people
1.3 定义一个结构体变量
数据类型 变量名;
int a;
struct 结构体名 变量名;
struct people p = {“zhangsan”,18};
1.4 访问
1.4.1 结构体变量名.成员
1.4.2 结构体指针变量->成员
数据类型 *指针变量名;
struct people *指针变量名;
1.5 字节对齐
字节对齐:一次性分配多少个字节
自然对齐(32OS):
char:1字节对齐
short:2字节对齐
int:4字节对齐
long:4字节对齐
float:4字节对齐
double:4字节对齐方式,分配的时候分配两次
注意:按照成员中最大的那个对齐
节省结构体空间的办法:
- 将成员中最大的放到最前面
- 位域or位段
未优化前:
优化之后:
/1字节8位,int 4字节,共32位
注意:不能使用标准输入对位域进行输入
day2
- 起别名
方法1:
方法2:
- 内存分区
- malloc和free
3.1 malloc
头文件:
#include <stdlib.h>
函数原型:
void *malloc(size_t size);
函数功能:申请空间
参数:要申请的空间的大小
返回值:成功返回申请到的空间的首地址,失败返回NULL
注意:
- malloc申请到的空间是没有名字的
- malloc申请到的空间是一片连续的内存空间
3.2 free
void free(void *ptr);
参数:申请到的空间的首地址
3.3 memset
头文件:
#include <string.h>
函数原型:
参数1:要填充的空间的首地址
参数2:要填充的字符
参数3:要填充的空间的大小
char buf[30] = {0};
while(1)
{
memset(buf,0,sizeof(buf));//清空
gets(buf);
}
day3
- 自定义头文件
.h文件
“”:编译器从用户的工作路径开始搜索头文件
<>:编译器从系统库路径(/usr/include)下开始搜索头文件
- 文件编译
作用:避免头文件重复引用
#ifndef 标号(一般用大写表示,把.变成_)
#define 标号
- 头文件
- 宏定义
- 结构体类型的定义
- 枚举类型的定义
- 函数声明
#endif
- gcc编译流程
程序的编译要经历预处理、编译、汇编、连接四个阶段
方法1:
预处理(处理以#开头的文件):gcc -E stu.c -o stu.i
编译(生成汇编语言):gcc -S stu.i -o stu.s
汇编(将汇编语言转成机器代码):gcc -c stu.s -o stu.o
链接(将所有的机器代码汇集生成一个可执行文件):gcc stu.o -o stu
方法2:
将gcc的前四步合四为一
gcc stu.c -o stu
- 多文件编译(解决单独编译出错的文件)
多文件编译工作原理:
4.1 将gcc的前三个阶段合三为一
4.2 将所有的机器代码汇集生成可执行文件
- make工程管理器
make会在当前路径下找一个叫做Makefile/makefile(M大小写都可以)的文件
5.1 Makefile的命名规范
目标文件1:依赖文件1
(Tab键)依赖文件1是如何生成目标文件1
目标文件2:依赖文件2
(Tab键)依赖文件2是如何生成目标文件2
注意:
- 一个Makefile中可以有多个目标文件
- 如果两个目标之间没有依赖,系统默认只执行第一个目标
没有依赖关系:
有依赖关系:
- 执行make命令时,需要指定目标是什么,如果没有指定系统默认执行第一个目标文件
- 目标文件可以没有依赖文件
5.2 解决假目标的办法
在最前面加上.PHONY(必须大写)
5.3 预定义变量
CC :编译器选项的名称,默认为cc
CFLAGS:编译器的选项,无默认值
RM:程序删除的名称,默认为rm -f
5.4 自定义变量
OBJ和OBJS,一个用于存放可执行文件,一个用于存放所有的依赖文件
5.5 自动变量
$@:目标文件
$^:所有的依赖文件
$<:第一个依赖文件
5.6 变量定义的两种方式
5.6.1 递归方式 VAR=var
注意:后面的值会影响前面的结果
5.6.1 简单方式 VAR:=var
5.7 嵌套Makefile
include(.h文件)、obj(*.o)、src(*.c)、bin(可执行文件)
1、先编写总控Makefile,书写自定义变量 or 预定义变量
2、进入src中编写Makefile,将所有的.c文件生成.o文件并且移动到obj中
3、进入obj中编写Makefile,将所有的.o文件生成可执行文件,并移动到bin目录中
- 编写总控Makefile,设置执行顺序,先执行src中的Makefile,然后再执行obj中的Makefile
6、枚举
使程序变得更加语义化
#define INPUT 1
#define OUTPUT 2
7、共用体
1.所有成员的首地址都是一致的
2.所占的内存空间的大小由成员中最大的那个决定
7.1 判断大小端
day4
- 递归
定规则自己执行
5!
5 * 4! return 120
4 * 3! return 24
3 * 2! return 6
2 * 1! return 2
1! return 1
- gdb调试器
编辑器:vim、gedit
编译器:gcc
调试器:gdb
(1)编译的时候添加-g参数
gcc -g error.c -o error
- 启动gdb调试器
gdb error
- 设置断点
b main(从main函数开始调试)
b 行号
- 运行(r)
- 其它参数
n:下一步(不进入子函数)
s:下一步(进入子函数,包括库函数)
p a:打印a的值
c:跳出循环 or 函数
quit:退出
- 函数指针
定义一个指向整型的指针:int *p = NULL;
定义一个指向整型指针的指针:int **pp = NULL;
定义一个指向整型数组的指针,该数组有3个元素:int (*p)[3] = NULL;
struct student
{
char name[20];
int age;
};
定义一个指向结构体的指针:struct student *p = NULL;
int add(int m,int n);//数据类型:int (int,int)
定义一个指向函数的指针:int (*p)(int,int);
回调函数:
- 指针函数
返回值为指针的函数
- 什么是嵌入式
嵌入式系统是以应用为中心,以计算机技术为基础,并且软硬件可裁剪,适用于对功能、可靠性、成本、体积、功耗有严格要求的专用计算机系统
- Linux的发展史
- Linux的发行版本
- shell的类型
Bourne Shell: 最早的Shell
C Shell
Ksh
Z Shell
Bourne Again Shell (bash)
- shell
9.1 shell命令、shell、shell脚本的本质区别
shell命令:用户向内核发出的控制请求,与之交互的文本流
Shell是一个命令行解释器,将用户命令解析为操作系统所能理解的指令,实现用户与操作系统的交互。
shell脚本:一堆命令的集合
9.2 shell命令的格式
命令 [选项] [参数];
[]:表示可以省略
选项:功能
参数:操作的对象
注意:
- 三者之间必须有空格
- 若将多个命令写在一行,用分号隔开
(3)如果一条命令不能在一行写完,使用反斜杠(\)标明该命令未结束
9.3 用户系统相关命令
用户切换命令
su - 用户名;//切换用户,系统当前工作路径以及环境变量都会发生改变
su - 等同于 su - root
su root//切换到root用户,系统当前工作路径以及环境变量都未发生改变
注意:一般情况下不要切换到root用户,要使用的话在命令最前面添加sudo
9.4 系统管理命令
ps:显示当前系统中由该用户运行的进程的列表
ps -ef:查看所有进程及其(PID)进程号、系统时间、命令详细目录、执行者等
ps aux:除了可以显示ps-ef的内容外,还可以显示CPU及其内存的占用率
pstree:将所有的进程按照树状图显示
top:动态显示进程
ps axj
kill:输出指定的信号给指定的进程
kill -l:列出所有可用的信号名称
9.5 磁盘相关命令
fdisk:查看硬盘分区情况及对硬盘分区进行管理
fdisk -l:列出文件系统的分区情况
注意:使用fdisk的时候必须使用root权限
free:查看当前系统的内存使用情况
df:查看文件系统的磁盘空间占用情况
du:统计目录or文件所占磁盘空间的大小
day5
- 文件目录相关命令
LinuxOS下有7中文件类型:
- 普通文件 -
- 目录文件 d //directory目录
- 字符设备文件 c
- 块设备文件 b //block 块
- 链接文件 l
- 管道文件 p //pipeline 管道
- 套接字文件(socket) s
1.1 chmod
作用:改变文件的访问权限
方式1:
u:文件拥有者
g:文件所属的用户组
o:其他人
a:所有者
+:增加权限
-:删除权限
=:设置权限
方式2:
- rw- rw- r-- 1 linux linux 126 7月 24 23:10
文件的类型 拥有者 用户所在组 其他人
注意:权限一般用8进制数表示 -表示没有权限,用0表示,有权限用1表示
rw- rw- r--
- 110 100 //664
r-x rw- --x
101 110 001 //561
-
- chown
作用:修改文件所有者和组别
注意:使用时必须使用root权限
修改用户:
修改组:
同时修改用户和组:
1.3 chgrp
作用:修改用户所在组
注意:必须使用root权限
1.4 grep
作用:在指定的文件中搜索特定的内容
grep 字符串 文件名
-n :显示行号
1.5 alias
作用:起别名(一次性的),想要永久有效的话添加到.bashrc(家目录下)中
1.6 wc
-l:统计这个文件有多少行
-c:统计这个文件有多少个字符
1.7 查看文件
cat 文件名;//只适合查看比较短的文档
more 文件名;//适合查看比较长的文档,按回车向下翻一行,按空格向下翻一页
less 文件名;//more的加强版,适合看比较长的文档,按回车向下翻一行,空格向下翻一页,支持上下箭头
2、特殊字符
*:匹配任意长度的字符串(任意个)
?:匹配一个长度的字符(任意一个)
[....]:匹配其中指定的一个字符
[ - ]:匹配指定的一个字符范围
[^...]:除了其中指定的字符,均可匹配
注意:以上指令只针对一个字符,*除外
2.1 管道
|:将前一个命令的输出作为后一个命令的输入
注意:一般不单独使用
2.2 输出重定向
> :如果文件不存在则新建,如果文件存在则清空文件中的内容
2.3 追加重定向
>>:如果文件不存在则新建,如果文件存在则追加在文件的末尾
2.4 输入重定向
2.5 将命令产生的错误信息输出到文件中
3、ln
3.1 硬链接
利用Linux中为每个文件分配的物理编号---inode建立链接
3.2 软链接(符号链接)
利用文件的路径名来建立链接,通常建立软链接使用的是绝对路径而不是相对路径
创建软链接:
创建硬链接:
软链接和硬链接的区别:
相同点:
ln命令会保持每一处文件的同步性,不论改动了哪一处,其它文件都会发生相同的变化
不同点:
软链接会在用户选定的位置上生成一个文件镜像,不会重复占用磁盘空间,平时用的最多的就是软链接
硬链接会在用户选定的位置上生成一个和源文件大小相同的文件。
4、压缩打包相关命令
4.1 压缩工具
gzip、bzip2
注意:以上只能压缩文件,不能压缩目录
压缩:
- gzip 文件名,压缩的后缀为 .gz
- bzip2 文件名,压缩的后缀为.bz2
解压:
方式1:
- gunzip 压缩后的文件名
- bunzip2 压缩后的文件名
方式2:
- gzip -d 压缩后的文件名
- bzip2 -d 压缩后的文件名
4.2 tar
作用:对目录进行打包或者解包,后缀为.tar
-c:打包
-x:解包
-v:显示详细的处理过程
-f:指定包文件名(该参数必须放在最后一个)
-z:调用gzip来压缩打包文件,与-x连用时调用gunzip完成解压缩
-j:调用bzip2来压缩打包文件,与-x连用时调用bunzip2完成解压缩
先打包
再压缩
先解压
再解包
将打包压缩一体化:
将解压解包一体化:
- Linux的环境变量
env:查看所有的环境变量
为什么所有的路径下都认识ls?
5.1 临时添加
注意:只对当前终端有效
5.2 永久添加
(1)sudo vim /etc/profile
(2)在文件末尾添加export PATH=$PATH:/home/linux/23071/linuxC/day5
(3)重启 or source /etc/profile
重启:sudo reboot
关机:sudo shutdown -h now (立刻) sudo shutdown -h +10 (10分钟后关机)
- Linux用户管理命令
6.1 相关配置文件
/etc/passwd:系统能够识别的用户清单
/etc/shadown:加密的用户清单,只有超级用户可以访问这个文件
/etc/group:包含了UNIX组的名称和每个组中的成员列表
6.2 创建用户
sudo adduser 用户名;
6.3 删除用户
sudo deluser --remove-home 用户名;
6.4 修改用户的密码
sudo passwd 用户名;
6.5 新建组
sudo groupadd 组名;
6.6 删除组
sudo groupdel 组名;
6.7 修改用户所在组
sudo usermod -g 目标组 要修改的用户;
- 共享文件
7.1 通过winscp
查看ip地址:ifconfig
登录winScp
注意:如果还是不行,添加网络适配器,并配置成仅主机模式
7.2 通过linux中的共享文件夹
(1)虚拟机-->设置-->选项
共享文件夹在/mnt/hgfs/
day6
- Linux的软件管理
- 换源
软件源配置文件/etc/apt/sources.list
-
- 下载
- sudo apt-get update //刷新软件源
- sudo apt-get install 包名
- 卸载
sudo apt-get remove 包名
-
- 测试网络
-
- 网络配置
- 虚拟机-->设置-->网络适配器
- 编辑-->虚拟网络编辑器
-
- linux下配置静态ip
-
- windows下配置静态ip
网络和internet设置-->更改适配器选项
- 网络基础知识介绍
IP地址:主机的唯一标识
2.1 IP地址的分类
A类IP地址:
由1字节的网络地址+3字节的主机地址,网络地址最高位必须是0
地址范围:1.0.0.0 ~126.255.255.255
B类IP地址:
2字节的网络地址+2字节的主机地址,网络地址最高位必须是10
地址范围:128.0.0.0 ~ 191.255.255.255
C类IP地址:
3字节的网络地址+1字节的主机地址,网络地址最高位必须是110
地址范围:192.0.0.0 ~ 223.255.255.255
D类
E类
2.2 子网掩码
作用:判断主机发送的包是向内网发送还是向外网发送
网络地址全是1,主机地址全是0
1111 1111 1111 1111 1111 1111 0000 0000
255 255 255 0
192.168.0.10 192.168.2.12 192.168.0.2
& 255.255.255.0
192.168.0.0 192.168.2.0 192.168.0.0
2.3 网关
如果想向外网发送数据,就必须经过网关
2.4 DNS服务器
由解析器和域名服务器组成
注意:域名必须有一个IP地址,但IP地址不一定有域名
- shell脚本
一堆命令的集合
c语言(强类型语言,对数据类型分的很清楚),编译性语言 gcc 1.c ./a.out
shell脚本(弱类型语言),解释性语言,不需要编译 ./1.sh
3.1 如何创建shell脚本
1、创建一个脚本文件,后缀为.sh
vim 1.sh
- 编辑shell脚本
- 执行时权限不够,需要人为的去添加
chmod 777 1.sh or chmod u+x 1.sh
- 运行
./1.sh
3.2 shell变量
3.2.1 自定义变量
shell允许用户建立 变量存储类型,但它不支持数据类型,任何被赋值给变量的值都被解释为一串字符。
命名规范:
- 由数字、字母、下划线组成,且开头不能为数字
- 在shell中变量一般用大写表示
注意:
- 等号的左右两侧不能有空格
- 去变量的值时,在变量前面添加$
- 在shell中,字符串用双引号或单引号都可以
3.2.2 位置参数
3.2.3 预定义变量
$#:包含命令行参数的个数
$@:包含所有的命令行参数
$*:包含所有的命令行参数
$?:包含前一个命令的退出状态,正常退出返回0,反之为非0 (shell中,0为真,非0为假)
$$:包含正在执行的进程号(PID)
案例1:在当前目录创建一个文件夹,如何判断该文件夹是否创建成功
案例2:在家目录创建一个叫做mydir的目录,在该目录中创建一个1.txt,然后向1.txt中写入”hello shell”
3.2.4 环境变量
env:查看所有的环境变量
3.3 shell程序和语句
3.3.1 说明性语句
#:注释
3.3.2 功能性语句
3.3.2.1输出
echo :自带换行
echo -n:不换行
3.3.2.2 输入
方式1:
方式2:
方式3:
方式4:
想要实现输出”hello shell “ ,”23071”
` `:反引号
3.3.3 expr
expr用于简单的整数运算,包括+、-、\*、/、%
注意:expr和变量以及变量和运算符之间必须添加空格
交叉编译工具链:
day7
- test
字符串、整数、文件属性
-
- 测试字符串
s1 = s2 测试两个字符串的内容是否完全一致
s1 != s2 测试两个字符串的内容是否有差异
-z s1 测试s1 字符串的长度是否为0
-n s1 测试s1 字符串的长度是否不为0
注意:[]的左右两侧必须有空格
-
- 测试整数
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
-
- 测试文件属性
-d name 测试name是否一个目录
-e 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 更旧
- shell控制语句
2.1 选择语句
2.1.1 单分支选择
if [ 表达式]
then
语句
fi
2.1.2 双分支选择
if [ 表达式 ]
then
语句1
else
语句2
fi
2.1.3 多分支选择
if [表达式1]
then
语句1
elif [表达式2]
then
语句2
...
elif [ 表达式n ]
then
语句n
else
语句n+1
fi
2.1.4 case
case 字符串变量 in
模式1)
命令表1
;; //类似与break,但是;;不能省略,最后一个可以省略
模式2 | 模式3)
命令表2
;;
.........
模式n)
命令表n
;;
*)//类似于c中的default
命令表n+1
;;
esac
2.2 循环语句
2.2.1 for语句
for 变量 in 单词表
do
语句
done
方式1:
方式2:
方式3:
方式4:
注意:{ }内不能写变量
方式5:
2.2.2 while语句
while [表达式]
do
语句
done
案例:打印9*9乘法口诀表
break n:跳出n层循环
continue:结束本次循环,开始下一次循环
3、函数
方式1:
函数名()
{
}
方式2:
function 函数名()
{
}
调用:
方式1:
变量=`函数名 形式参数列表`
注意:函数中的所有标准输出传递给了主程序中的变量
方式2:
函数名 形式参数列表
echo $?
案例:
- 判断用户主目录是否有file-dir和dir-dir目录
如果这两个目录存在,询问是否删除这两个目录
如果用户的是Y,将这两个目录删除,重新创建这两个目录
如果是N,取消删除
如果上述的目录不存在,则创建这两个目录
- 请用户输入一个路径,将这个路径下的文件拷贝到file-dir这个目录,将
这个路径下的目录拷贝的dir-dir目录
- 统计拷贝的文件和目录的个数