嵌入式linux第一阶段笔记

1.虚拟网络编辑器(vm):三种模式:(VMnet0)桥接模式(vm和windows公用同个网络(同个物理端口)),(VMnet1)仅主机模式,(VMnet8)NAT模式(vm连接一个虚拟的路由(WAN,LAN),windows也连在里面(LAN口里),形成一个局域网,具体的格式由WAN口发送)
2.安装完Ubuntu18.0.4后(用户名:lkb 密码:lkb),然后要创建root并将root升级为超级管理员
打开终端,输入:sudo passwd root,然后输入密码(此时是注册时的密码)-输入给root创建的密码(此时123)-su -(将root升级为超级用户),su - 用户名(从超级用户切换到普通用户)
3.更新操作系统的源泉,以便可以下载最新的安装包
upt-get update
4.添加vim编辑器:apt install vim-nox(推荐下载vim-nox而不是vim)-输入y确定-等待下载完成-之后直接输入vim即可-退出(:q),强退(:q!)
5.vim:命令模式:esc
编辑模式:i
6.sshd:SecureCRT客户端
SSHD服务端 (更新SSHD服务端:apt-get install openssh-server)
通过CRT连接虚拟机的ip地址(ifconfig),来完成远程登录
7.SecureCRT下有个Zmodem,rz是从window中传文件到vm中,sz是从vm中传文件到windows中
8.samba服务(windows和linux之间数据通信)也就是SMB:Server Message Block
9.CRT下安装sanba服务器:sudo apt-get install samba
10.samba服务器的配置:/etc/samba/smb.conf(配置需要共享哪个目录,以及这个目录的访问权限)
sudo vi samba
然后在末端添加
[lkb_share]
comment = My share
path = /home/lkb/lab
writable = yes (可写)
browseable = yes (可浏览)
11.在/etc/samba下创建samba用户:sudo smbpasswd -a lkb ,密码123
然后重启一下smbd,nmbd; sudo /etc/init.d/smbd restart,sudo /etc/init.d/nmbd restart
12.在CRT里面ifconfig一下,获得ip地址,在windows端cmd,输入\\+ip地址
13.在CRT的/etc/samba 进入 /home/lkb/下,mkdir lab,进入lab/,然后就可以进入Samba访问了
14.第二种访问形式即是在windows计算机映射网络虚拟器,文件夹输入\\+CRT下的ip+lkb_share,然后在windows计算机出现了网络位置,相当于已u盘形式访问linux(可鼠标操作复制黏贴,不用写指令)
15.安装source insight并破解(百度)
16.在虚拟机共享文件夹下新建Myapp文件,在Myapp文件下新建pro文件,用source insight新建工程放入pro文件下,.c文件放入Myapp下(pro的上一层目录)
17.source insight添加已有工程,然后在project files将添加的工程右键Synchronize Files,将文件同步进去
18.在linux下输入gcc -v 可查看是否安装了gcc,没有的话可以用指令apt-get install gcc安装
19.可以使用vi xx.c新建c文件(后缀名必须为.c,gcc对后缀名非常敏感),然后gcc -o 输出的文件名 xx.c来编译,无错误则./输出的文件名即可查看编译结果
20.预处理:cpp -o xx.i yy.c
替换:gcc -E
编译:gcc -S
汇编:gcc -c
链接:gcc -o
21.#include后用""包含的.h文件是自定义的,<>包含的是系统库的
22.not find 头文件的话可以用gcc -I跟查找文件的目录
23.#define 宏名 宏体 (宏体最好加上括号)
24.预定义宏
__FUNCTION__ :函数名
__LINE__:行号
__FILE__:文件名
25.gcc -DABC ==#define ABC
26.# 字符串化 #x === "x"
## 连接符号 day##x === dayx
27.数据类型:char,short,int,long,unsigned,signed,float,double(8字节),void
28.struct(结构体):元素之间的和
struct myabc{
unsigned int a;
unsigned int b;
unsigned ing c;
}
struct myabc mybuf;
union(共用体):公用起始地址的一段内存
union myabc{
char a;
int b;
}
union myabc abc;
29.sizeof()默认是unsigned long 类型,则基本不用%d 而是用%lu
30.enum {MOD,TUE,WED}(被命名的整型常量的集合),从左到右依次加1,如果第一个没有赋值,默认为0
31.类型修饰符
auto:分配的内存可读可写的区域(区域如果在{}里面,即在栈空间里面)
register:限制变量定义在寄存器上的修饰符
定义一些快速访问的变量,编译器会尽量的安排CPU的寄存器去存放这个定义的变量,如果寄存器不足时,这个定义的变量还是放在存储器中(内存(存储器) 寄存器)

&取地址这个符号对register不起作用
static:静态变量
const:常量的定义,只读的变量
volatile:告知编译器编译方法的关键字,不优化编译
修饰变量的值的修改,不仅仅可以通过软件,也可以通过其他方式(硬件外部的用户)
32.算数运算符(+,-,*,/,%)
%:n%m=[0~m-1]
逻辑运算{ ||、%% (A||B(当A为真的时候就不用判断B了),A&&B(当A为假的时候就不用判读B了),AB交换结果是不一样的)
>、>=、<、<=
!
? :
}
位运算{<<(左移,乘以2的倍数)、>>(右移,除以2的倍数)
&、|、 (将某一位置为高电平:a|(0x1<<5),清除某一位:a&~(0x1<<5))
^, ~ (a=a^b,b=a^b,a=a^b,可以互换ab两个值)

33.-1的二进制表达式:11111111
10000001
取反后 11111110
补码为 11111111(即为计算机中-1的二进制表达式)
34.指针:内存类型资源地址、门牌号的代名词
在32bit系统中,指针就4个字节
35.指针读取内存的方法:int *p 读取32位地址,char *p读取8位地址
36.const:常量、只读(不能变)
左数右指
37.char *p ="hello";此时无法通过*p='a'来修改其中的第一个字符
char buf[]={"hello"};
char *p2=buf;此时可以通过*p2='a'来修改其中的第一个字符
38.指针的加法、减法运算,实际上加的是一个单位,单位的大小可以使用sizeof(p[0])
p++,p--:更新地址
p+1:[*p+1*(sizeof(*p))]
*(p+n)=p[n]
39.指针必须是同类型的比较才有意义
指针跟一个特殊值进行比较 0x0:地址的无效值,结束标志
40.二级指针:指向指针的指针,即一个指针指向的是另一个指针
int a =100;int *p1 = &a;int **p2 = &p1;
41.数组的定义:定义一个空间:1、大小 2、读取方式
数据类型 数组名[m] m的作用域是在申请的时候
数组名是一个常量符号,一定不要放到=的左边
42.字符拷贝函数的原则:内存空间和内存空间的逐一赋值的功能的一个封装体(strcpy,strncpy)
一旦空间中出现了0这个特殊值,函数就即将结束
43.非字符串空间拷贝:memcpy(void *dest,const void *src,size_t n)
44.定义一个指针,指向int a[10]的首地址:int *p1=a;
定义一个指针,指向int b[5][6]的首地址:int (*p2)[6]=b;
45.字节对齐: 在结构体中,结构体最终的大小一定是4的倍数
结构体里成员变量的 顺序不一致,也会影响到它的大小
小于四字节的按四字节算,大于的按八字节或以上算
例如:struct abc{ struct abc2{
char a; char a;
short b; int c;
int c; short b;
}: (8字节) }:(12字节)

46.内核分布
内核空间 应用程序不许访问
-----------------------------3G
栈空间 局部变量 RW (函数执行完自动释放空间)
------------
运行时的堆空间 malloc
----------------
全局的数据空间(初始化的,未初始化的) static RW data(数据段),bss(未初始化的数据段)
只读数据段 "Hello World" 字符串常量 (双引号其实就是一个地址,里面的值修改不了) R text(代码段)
代码段 R text(代码段)
---------
0x0
47.size + 编译后的文件名 则可以查看函数的代码段运行的具体数据
nm + 编译后的文件名 则可以看段名
48.堆空间:运行时才有,可以自由,自我管理的分配和释放的空间,生存周期是又程序员来决定
分配:malloc(),一旦成功,返回分配好的地址给我们,只需要接受,对于这个新地址的读法,又程序员灵活把握,输入参数指定分配的大小,单位就是B
char *p; p=(char *)malloc(n);if(p==NULL){ error } malloc(n*sizeof(char))
释放:free(q)
栈空间:运行时才有 ,函数一旦返回就释放,生存周期内是函数内
只读空间:静态空间,整个程序结束时释放内存,生存周期最长
49.函数具备三要素:函数名(地址),输入参数,返回值
50.例子:
int (*myshow)(const char *,...);(和printf函数一样的函数名)
printf("the printf is %p\n",printf);
myshow=printf;
myshow("===========\n");
通过上面这样操作,myshow就具备了printf一样的功能,输出=========
51.地址传递:上层调用者让下层子函数修改自己空间值的方式
类似结构体这样的空间,函数与函数之间调用关系
连续空间的传递
52.const char *p:只读空间,为了让空间看看
char *p:该空间可能修改
53.字符空间:char *p strlen,strcpy (结束标志:0)
非字符空间:unsigned char *p,int *p......,memcpy,void * (结束标志:数量)
结束标志:内存里面存放了0x00(1B),字符空间
非字符空间0x00,不能当成结束标志
54.返回值返回类型:基本数据类型、指针类型(空间),不能返回数组
55.返回连续空间类型:指针作为空间返回的唯一数据类型(函数内部实现:1.静态区 2.只读区 3.堆区)
地址:指向的合法性
作为函数的设计者,必须保证函数返回的地址所指向的空间是合法的(不是局部变量)
例子:char *fun(void)

char buf[]="hello world";
return buf;

int main()
{
char *p;
p=fun();
printf("the p is %s\n",p);
return 0;
}
这个例子输出不来hello world,因为在fun函数中,buf[]是局部变量,函数一返回地址就自动释放,而函数返回buf其实就是返回buf[]的地址,故返回的是NULL。
在 char buf[]="hello world"; 前加static即可将局部变量变为静态变量,存放在全局数据区,函数返回地址就不会被释放
56.嵌入式工程系面试必备的0x10道题目:(网页收藏夹查看其他题目以及解析)
1.用预处理指令#define 声明一个常熟,用以表明1年中有多少秒(忽略闰年问题)
#define 宏名 宏体 (宏名:大写字母表示)
#define SECOND_OF_YEAR (365*24*3600)UL (UL表明无符号长整型)
2.数据声明
(1)一个整型数:int a;
(2)一个指向整型数的指针:int *a;
(3)一个指向指针的指针,它指向的指针是指向一个整型数:int **a;
(4)一个有10个整型数的数组:int a[10];
(5)一个有10个指针的数组,该指针是指向一个整型数的:int* a[10];
(6)一个指向有10个整型数组的指针:int (*a)[10];
(7)一个指向函数的指针,该函数有一个整型参数并返回一个整型数:int (*a)(int);
(8)一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数:int (*a[10])(int);
3.修饰符的使用总结
(1)关键字static的作用是什么?
修饰局部变量:默认局部变量在栈空间存在,生存期比较短
加上static后局部静态化,局部变量在静态数据段保存,生存期非常长
修饰全局变量:编译时防止重命名,限制变量名只在本文件内起作用
修饰全局函数:编译时防止重命名,限制该函数只在x本文件内起作用
(2)关键字const有什么含意
C:只读,建议性,不具备强制性 !=常量
C++:常量
(3)关键字volatile有什么含意?并给出三个不同的例子
防止C语言编译器的优化
它修饰的变量,该变量的修改可能通过第三方来修改
a.并行设备的硬件寄存器(如:状态寄存器)
b.一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
c.多线程应用中被几个任务共享的变量
4.位操作
嵌入式系统总是要用户对变量或寄存器进行位操作,给定一个整型变量a,写两段代码,第一个设置a的bit3,第二个清除a的bit3,在以上俩个操作中,要保存其他位不变
unsigned int a;
a|=(0x1<<3);
a&=~(0x1<<3);
5.访问固定内存位置
在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66,编译器是一个纯粹的ANSI编译器,写代码去完成这一任务
int *p=(int *)0x67a9;
p[0]=0xaa66;
或者
*((int*)0x67a9)=0xaa66;
或者
((void(*)(void))0x67a9();
6.写一个"标准"宏MIN ,这个宏输入两个参数并返回较小的一个。
#define MIN(A,B) ((A) <= (B) ? (A) : (B))
7.预处理器标识#error的目的是什么?
#error预处理指令的作用是,编译程序时,只要遇到#error就会生成一个编译错误提示消息,并停止编译
8.嵌入式系统中经常要用到无限循环,你怎么样用C编写死循环呢?
(1).while(1){};
(2).for(;;){};
(3).Loop:
...
goto Loop;

LINUX
57.ctrl+alt+F2,F3,F4,F6:图形转命令界面
ctrl+alt+F7:命令转图形界面
如果不是从图形界面切换到tty模式,而是系统启动时候直接进入的命令行模式,在登陆后可以使用”startx”来启动图形界面。
58.文件系统分类
磁盘文件系统:NTFS.EXT3
闪存文件系统:JFFS2,YAFFS
数据库文件系统:BFFS,WINFS
网络文件系统:NFS
虚拟文件系统:VFS(Proc)
59.Linux文件类型
普通文件:-
目录文件:d
链接文件:l
块设备:b
字符设备:c
Socket:S
普通文件:p
60.Linux文件属性
蓝色:目录
绿色:可执行
浅蓝色:连接
红色:压缩
灰色:其他n
黄色:字符设备
61.命令行格式
$command [option(s)] [arguments]
命令行 空格 选项 空格 参数
62.命令行编辑
命令行别名使用
alias alias-name='value' 建立别名
alias 列出已经建立的别名列表
unalias 取消别名
63.shell的特殊字符
1.通配符: *,?,[]
*,通配0个或多个字符
?,通配任意单个字符
[s],通配某个范围内的任意一个字符
2.一行执行多条指令: ;(例如:cd ; ls 先进入根目录再ls所有)
3.输入输出重定向:>,<,>>
输出重定向:>,>>
>:将一个命令的输出放入文件而非屏幕 (例如 pwd > 1.txt,在1.txt中会显示当前的目录)
>>:输出重定向但不会把原文件覆盖,在原文件末尾追加
输入重定向:< 从标准输入设备键盘输入
4.管道符:|
将一个进程的输出作为另一个进程的输入(例如:ls -l /etc | more 让etc下的目录按分页显示)
5.其他,%,$,~
%:作业控制,提示符等
$:取某一列的值,取变量值等
64.联机帮助
man name
man -k keyword
spacebar 翻屏或翻页
Enter 翻行
b 向前翻一屏或一页
f 向后翻一屏或一页
q 退出
/string 查找前面符合string指定的信息
n 查找下一个符合string指定的信息
65.清屏
clear
66.历史记录
history
history n
!n
!1
方向上键
67.查看文件和目录
pwd :显示当前工作目录
cd:改变当前工作目录
ls:列出当前目录的文件和子目录
ls -a:列出所有目录、子目录、文件和隐藏文件
ls -R:列出从当前目录开始的所有的子目录、文件并且一层层往下显示
ls -F:列出文件、文件名并显示出文件类型
ls -t:以修改时间为时间倒叙来列出文件、子目录
ls -l: 以长列表格式显示文件、目录的详细信息
file:file filename 列出文件类型
68.创建文件
touch filename
filename 不存在则创建一个新的空文件
filename 存在则更新该文件的修改访问时间
69.创建目录
mkdir [-p] directory_name
-p 目录不存在时可以建立目录
70.删除文件
rm [-i/f] filename(s)
-i 询问是否删除
-f 强制删除
71.删除目录
rmdir directory_name(s) 删除空目录
rm -r[i] directory_name(s)
-r 删除非空目录
-i 删除前访问是否删除
72.显示文本文件内容
cat:不分屏显示文本内容
把小文件连接成大文件
cat filename(s)
more:more filename(s)分屏显示
spacbebar 向下显示一屏
Enter 向下显示一行
b 向上一屏
f 向下一屏
h 显示帮助菜单
q 退出
/string 查找字符串string
n 查找下一个string
head:查找文件的前多少行
head [-n] filename(s)
tail:查找文件的末尾多少行
tail [-n] filename(s)
73.拷贝和移动文件目录
cp
拷贝复制文件目录
拷贝文件
cp [-i] source_file destination_file
cp [-i] source_file(s) destination_directory
-i选项作用,当目标文件存在,会询问是否覆盖,没有-i选项则不询问直接覆盖

拷贝目录
cp -r source_directory(s) destination_directory(s)
mv
移动文件目录或重命名文件目录
mv [-i] source_file target_file 重命名源文件为目标文件
mv [-i] source_file target_directory 移动文件到目标目录
74.文件目录权限
r 读权限:可以打开文件、目录读取查看
w 写权限:对文件、目录可以编写更改
x 执行权限:对文件可执行(可执行文件)、对目录可查找该目录下的内容
- 没有权限:如ls -l -rwxr-xr-x
权限所属对象
拥有者:生成文件或目录时登陆的当前人,权限最高,用u表示
同组人:系统管理员分配的同组的一个或几个人,用g表示
其他人:除拥有者,同组人以外的人,用o表示
所有人:包括拥有者、同组人及其他人,用a表示

chmod:修改文件目录的访问权限,修改权限的前提条件是在修改权限时要注意自己是文件
(1)使用字母表示权限
chmod mode filename
mode: who cp permission(s)
u 拥有者 = 设置权限 r
g 同组人 + 添加权限 w
o 其他人 - 删除权限 x
a 所有人
例如:chmod u=r,g+w,o-x filename
(2)使用八进制数字来表示权限
r w x
0 0 0 无权限
1 1 1 有权限
例如:chmod 555 filename
chown:更改某个文件或目录的属主和属组,可用于授权
chown [选项] 用户或组 文件
chown将指定文件的拥有者改为指定的用户或组,用户能是用户名或用户ID,组能是组名或组ID
文件是以空格分开的要改动权限的文件列表,支持通配符

-R 递归式地改动指定目录及其下的所有子目录和文件的拥有者
-v 显示chown命令所做的工作
chgrp:改动文件或目录所属的组
chgrp [选项] group filename
该命令改动指定指定文件所属的用户组,其中group能是用户组ID,也能是/etc/group文件中用户名的组名
文件名是以空格分开的要改动属组的文件列表,支持通配符
如果用户不是该文件的属主或终极用户,则不能改动该文件的组

-R 递归式地改动指定目录及其下的所有子目录和文件的属组
chgrp -R book /opt/local/book
改动/opt/local/book/及其子目录下的所有文件的属组为book
75.查找文件
find
find file path expression [action] 查找文件和目录
前提条件:要对被查找的目录及其所有子目录有读权限才能查找
查找选项:通过文件属性来查找
-name 按文件名
-user 按用户(文件属主)
-size 按大小
-mtime 按最后一次修改时间
-atime 按最后一次访问时间
-type 按文件类型 f:flie d:directory
-perm 按权限
例如:find / -name b*
locate
locate [-d <数据库文件>][--help][--version][keywords]
locate指令用于查找符合条件的文件,它会去保存文件与目录名称的数据库内查找合乎范本样式条件的文件或目录
-d<数据库文件>--database=<数据库文件>,设置locate指令使用的数据库
--help 在线帮助
--versio 显示版本信息
76.过滤与统计
grep:查出包含某些字符串的结果,对文件或输出结果进行过滤,大小写敏感
grep [option(s)] string filename
-l 忽略大小写
-v 反向匹配(查出不包含字符串的结果)
wc:统计文件或输出结果
wc [option(s)] filename(s)
-l 统计多少行
-w 统计多少个单词
-c 统计多少个字符
77.日期时间与进程查看
date:显示当前日期
cal:显示日历
cal 月份 年份
cal 显示当前月份的日历
cal 年份
ps:列出当前系统中已在运行的进程
进程,一个能完成一定功能的一个程序
ps [options]
ps -e 列出正在运行的进程
-f 列出一个完整的进程列表形式
-U 查找出由某个用户启动的进程
-auwx 列出一个完整的进程列表形式,形式与-f不一样
78.切换用户、设置普通用户的超级权限与关机重启
su
su 用户名
sudo
sudo 命令行
shutdown:安全的关闭或重启Linux系统
shutdown [-etFhknr][-t 秒数][时间][警告信息]
-c:当执行"shutdown -h 11:50"指令时,只要按+键就可中断关机的指令
-f:重新启动时不执行fsck
-F:重新启动时执行fsck
-h:将系统关机
-k:只是送出信息给所有用户,但不会实际关机
-n:不调用init程序进行关机,而由shutdown自己进行
-r:shutdown之后重新启动
-t<秒数>:送出警告信息和删除信息之间要延迟多少秒
[时间] 设置多久时间后执行shutdown指令
[警告信息] 要传送给所有登入用户的信息
#shutdown -r +10 系统在十分钟后关机并且马上重新启动
#shutdown -h now 系统马上关机且不重新启动
reboot
reboot的工作过程差不多跟halt一样,不过它是引发主机重启,而halt是关机,它的参数与halt相差不多
79.用户管理
用户密码设置要求:6-8个字符,至少包含2个字母,1个数字或特殊符合
不同于用户ID,不同于以前的密码,并且至少3个字符不同于以前的密码
修改密码命令:passwd
查找用户
id:查看用户ID(用户名),所属组ID(组名)
users:查看已经登陆到当前系统中的用户,只显示出用户名
who:查看用户的详细信息
who am i:查看当前用户自己的信息
whoami:查看当前用户自己的用户名
80.查看磁盘信息
du:显示磁盘使用摘要信息
du以Block为单位方式显示
-k 以k字节方式显示
-m 以m字节方式显示
-s 显示当前目录下的内容总的占用磁盘的大小,以Block为单位
以Block单位显示的数字是以k字节方式显示的数字的2倍:1k字节=2个Block
df:显示整个文件系统的空间使用磁盘情况
-k 以k字节方式显示
81.查看网络连接
ping:查看当前机器与另一台机器的联通状况
ping 主机ID/主机名
向ping后面的主机发送数据包,若被ping的主机有回复则表明是联通的
ifconfig:查看和配置当前机器的网络参数信息
ifconfig -a:显示查看当前机器的IP、Netmask、Gateway等网络信息
ifconfig eth0 up(down) 激活与关闭某个网络适配卡(关闭后ifconfig查看不到eth0,ifconfig -a可以查看到)
ifconfig etho [ipaddress] 或者 netmask [address] 设置IP和子网掩码 (重启Ubuntu后又恢复默认状态)
82.Linux下安装卸载应用程序的方式
安装包离线安装和卸载:dpkg
dpkg -i 安装包
dpkg -p 移除包和配置文件
源文件编译安装和卸载:配置configure、编译make和安装make install
程序管理包在线安装和卸载:aptitude
apt-get install 安装
apt-get remove -purge 卸载完全
83.vi:vi filename
filename不存在则创建filename文件并可编辑和保存退出
filename存在则打开文件编辑
vi使用的三种模式:命令模式(k 向上;j向下;h向左;l向右;0移动到行首;$移动到行尾;G移动到文件末尾;1G移动到文件首;[n]G移动到第[n]行;[n]+向下移动[n]行;[n]-向上移动[n]行)
输入模式
末行模式(set nu 设置行号;set nonu 取消行号)
通过vi打开或者新建一个文件的时候,按o进入下一行,按a进入当行下一个,按i当前位置输入
最后行(末行模式):按 : ! ?

GNU开发环境基础
84.GCC程序编译过程

预处理 编译 汇编 链接
c源代码---------->.i预编译文件------>.s汇编文件------>.o目标文件----->可执行文件
GCC支持的后缀名
.c:C原始程序
.C/.cc/.cxx:C++原始程序
.m:Objective-C原始程序
.i:已经预处理的C原始程序
.ii:已经预处理的C++原始程序
.s/.S:汇编语言原始程序
.h:预处理文件(头文件)
.o:目标文件
.a/.so:编译后的库文件,静态库和动态库
85.编译过程参数
-c:只编译不链接,生成目标文件
-S:只编译不汇编,生成汇编代码
-E:只预编译
-g:包含调试信息
-o file:指定目标输出文件
-Idir:搜索头文件路径
具体编译过程:
gcc -E xxx.c -o xxx.i
gcc -S xxx.i -o xxx.s
gcc -c xxx.s -o xxx.o
gcc xxx.o -o xxx (或者直接gcc xxx.c -o xxx,省略前面三步)
./xxx(执行可执行文件)
gcc -g xxx.c -o xxx (包含调试信息)
gcc -I+路径 xxx.c -o xxx(会在指定路径下寻找头文件)
86.库选项
linux下静态链接库和动态链接库格式
.a[libname.a]
.so[libname.so]
-static 静态编译
-shared 生成动态库文件、进行动态编译
-L dir 库文件搜索中添加路径
-fPIC 生成使用相对位置无关的目标代码,然后通常用于使用gcc的-static选项从该PIC目标文件生成动态库文件
编译静态链接库
1.先生成目标文件 .o
2.打包:ar crv [*.a][*.o]
调用静态链接库
gcc -o [file] [file.c] -L.
编译动态链接库
1.生成位置无关的目标代码gcc -fPIC -c [*.c]
2.gcc -shared -o [*.so] [*.o]
调用动态链接库
gcc -o [file] [file.c] -L.
87.警告选项
-w 关闭所有警告
-Wall 发出gcc提供的所有有用的警告
-pedantic 发出ansic的所有警告
88.优化选项
-Olevel 优化等级,一般只是最终发布的时候才用
89.gcc编译
编译和安装gcc工具包需要几个类库:gmp(需要依赖m4,直接sudo apt-get install m4即可),mpfr(需要依赖gmp),mpc(需要依赖gmp,mpfr)
将gmp,mpfr,mpc,gcc四个包解压到当前目录下,然后分别一次安装配置,顺序都是:./configure ---> make ---> sudo make install
90.gdb调试
gcc -g xxx.c -o xxx
gdb xxx (即可进入调试)
查看程序
打断点:b(reak) 函数名
b(reak) 行号
b(reak) 文件名:行号
b(reak) 行号 if 条件
查看断点:info break (简写:i b)
删除断点: delete 断点号(简写:d 断点号)
运行:r(un),c(ontinue),q(uit)
单步调试:n(ext) -- step over
s(tep) -- step into
f(inish) -- step return
继续运行:continue
打印值:p(rint)值
监控值:w(atch)值
wi(特别的模式)
91.Makefile
gnu的make作用:工程文件组织,编译成复杂的程序
安装及卸载我们的程序
新建三个.c文件 main.c,func1.c,func2.c,其中main.c的调用func1,func2
将这三个.c文件编译成main.o,func1.o,func2.o
新建makefile,最后输出hello
makefile里面写代码:hello:main.c func1.c func2.c
gcc main.c func1.c func2.c -o hello
然后make后生成hello
./hello执行

makefile里面代码可以换成:hello:main.o func1.o func2.o
gcc main.o func1.o func2.o -o hello
main.o:main.c
gcc -c main.c
func1.o:func1.c
gcc -c func1,c
func2.o:func2.c
gcc -c func2.c
可以在makefile里面再加入代码:
clean:
rm main.o func1.o func2.o hello
install:
cp hello /usr/local/hello
uninstall:
rm /usr/local/hello
然后直接make +clean/install/uninstall就可以执行了

Makefile由若干条的规则构成
每个规则又是这样的:
targets(目标):prerequisites(依赖)
command

1.makefile变量:
用户自定义变量:在新建的makeflile中,可以随便定义一个变量=xxx,要使用这个变量只需$(+变量)即可,如果在=前面加上:的话表明该变量不会递归(递归就是=号后边再有变量是不会去增加的)
预定义变量:AR :库文件维护程序的名称,默认值为ar
AS: 汇编程序的名称,默认值为as
CC: C编译器的名称,默认值为cc
CXX:C++编译器的名称,默认值为g++
ARFLAGS:库文件维护程序选项,无默认值
ASFLAGS:汇编程序选项,无默认值
CFLAGS: C编译器选项,无默认值
CXXFLAGS:C++编译器选项,无默认值
自动变量及环境变量:
$*:不包含扩展名的目标文件名称
$<:第一个依赖文件名称
$?:所有时间戳比目标文件晚的依赖文件
$@:目标文件完整名称
$^:所有不重复的依赖文件
2.make工作流程
make会在当前目录下找名字叫“Makefile”或“makefile”的文件
如果找到,它会找文件中的第一个目标文件(target)并把这个文件作为最终的目标文件
根据时间戳生成目标文件
递归去寻找目标文件依赖文件,并且递归生成(同样有时间戳问题)
3.引用其它makefile及makefile嵌套
包含:include pro/makefile
嵌套:subsystem:
cd subdir && gcc -c main.c
等价于:
subsystem:
gcc -c main.c -C subdir
4.条件判断(放在行开头,不能空格)
foo:
ifeq ($(CC).gcc)
.......
else
.......
endif
5.使用函数
6.makefile管理命令
-C dir 读入指定目录下面的makefile
-f file 读入当前目录下的file文件为makefile
-i 忽略所有命令执行错误
-l dir 指定被包含的makefile所在目录
7.伪目标:没有依赖关系,也不会生成文件
clean:
gcc -c main.c
但为了不和已经生成的同名文件冲突,我们可以指定clean是个伪目标
.PHONY:clean
clean:
gcc -c main.c
用伪目标生成多个文件
all:prog1 prog2 prog3
.PHONY:all
prog1:prog1.o utils.o
cc -o prog1 prog1.o utils.o
prog2:prog2.o
cc -o prog2 prog2.o
prog3:prog3.o sort.o utils.o
8.makefile规则
显示规则
隐式规则:
OBJS=kang.o yul.o
CC=gcc
CFLAGS=-Wall -o -g
davild:$(OBJS)
$(CC)$^ -o $@

问题:
源文件或者依赖文件很多怎么办?
makefile分开多文件或者分级
output不仅仅一个文件怎么办?
用多个makefile文件,相互include(嵌套)
使用伪目标make all
92.Autotools
1.建立hello.c
2.autoscan扫描,生成configure.scan文件
3.将 configure.scan改名成 configure.ac或者 configure.in :mv configure.scan configure.ac
4.编辑configure.ac文件
将第五行改成AC_INIT(hello,1.0,[email protected])
第八行增加 AM_INIT_AUTOMAKE(hello,1.0)
注释第七行
将最后一行改成 AC_OUTPUT(Makefile),让其最后输出文件为Makefile
5.aclocal 生成aclocal.m4和autom4te.cache文件
6.autoconf 生成configure文件
7.建立vi Makefile.am(am是automake的缩写)
写入:bin_PROGRAMS = hello
hello_SOURCES = hello.c
8.automake --add-missing
9.建立文件:touch NEWS README AUTHORS ChangeLog
10.再执行automake --add-missing 生成Makefile.in
11../configure生成configure.status 和Makefile
12.make 后即可生成hello
13../hello即可
14.sudo make install后就会在/usr/local/bin/hello下生成hello,这样在任何目录下面输入hello都可以执行hello.c
15.make dist后生成这个hello.c的压缩包,可以取出来供别人下载

//在第四步的时候可以不注释第七行,然后继续执行5,6步,接着执行autoheader 生成configure.h.in文件,然后接着从第八步开始执行

Autotools流程:
autoscan
aclocal
autoconf
[autoheader]
automake
93.Linux下eclipse的开发
Linux下安装Eclipse
JDK下载,安装及配置
Eclipse(CDT下载),安装
Eclipse使用(调试及编译)
1.下载jdk和eclipse安装包
2.复制到download下
3.解压
4.将解压的jdk文件夹复制到/usr/local/bin下
5.配置jdk环境 sudo vi /etc/profile
在第四行添加
export JAVA_HOME=/usr/local/jdk1.8.0_11
export PATH=$PATH:$JAVA_HOME/bin
6.进入解压到的eclipse文件夹下
7. ./eclipse启动eclipse

转载于:https://www.cnblogs.com/kb19970405/p/11075257.html

你可能感兴趣的:(嵌入式linux第一阶段笔记)