FreeRTOS
=========
以下内容全部基于ARM Cotex-M系统
* MCU的NVIC分组必须是第4组,这意味着所有中断的preemption priority是[0, 15],sub priority恒为0
* LIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY是调用FreeRTOS中断API的中断最大优先级。换句话说,所有调用FreeRTOS中断API的中断的优先级都必须大于等于这个值
GIT
====
git log
========
git log --oneline # 每个提交只显示一行
git log -n # 查看最近n个提交
git log --stat # 每个提交显示修改的文件以及增删行数
git log --graph [--all] # 用ascii字符显示分支树。--all是显示所有分支
子模块
======
添加子模块:
git submodule add <仓库地址> <本地路径> # 这会生成.gitmodules文件。然后你就可以push到github了
获取子模块:
# 当你git clone时,子模块只有目录而已,你得执行下面两条命令才行
git submodule init
git submodule update
删除子模块:
rm -rf 子模块目录 删除子模块目录及源码
vi .gitmodules 删除项目目录下.gitmodules文件中子模块相关条目
vi .git/config 删除配置项中子模块相关条目
rm .git/module/* 删除模块下的子模块目录,每个子模块对应一个目录,注意只删除对应的子模块目录即可
注意:
* 获取到子模块后,子模块里是没有任何分支的,建议每个子模块都新建一个分支
* 如果改了子模块而不推送子模块的话,子模块的远程仓库是不更新的
补丁
====
生成补丁:
git diff [旧ID] [新ID] >
git format-patch
检查补丁能否打上:
git apply --check
应用补丁:
git apply
git am
注意:
* 关于组合问题:
* git apply一般对应于git diff。这个比较简单,就跟unix的diff差不多,它会把补丁中的内容应用到工作区但不提交,你得手动提交
* git format-patch一般对应于git am。这两个操作会把提交信息一并打入,比git diff + git apply更加智能
* 其他组合我没试过
git fetch
==========
# 有时你需要检查当前仓库是否是最新的,但你又不想用git pull,因为你想先看一下远程仓库改了哪些,这时你可以用git fetch
git fetch origin master:tmp # 把远程仓库的master分支复制到本地的tmp分支
git diff tmp # 查看远程仓库作了哪些改动
git pull 或者 git merge tmp # 合并分支
git branch -d tmp # 删除临时分支
解决中文乱码
==========
git config --global core.quotepath false
栈(stash)
===========
注意:"git stash"仅仅是把工作区和仓库不同的部分压入栈中,已经压栈的代码相当于仓库的代码。例如:
$ echo "" > demo.txt
$ echo "1" >> demo.txt
$ git stash save "V1"
$ echo "2" >> demo.txt
$ git stash save "V2"
此时如果你git stash pop,那么V2这个栈就会恢复,然而demo.txt仅仅是"2"而已,不是"1\n2"
git stash # 把工作区的代码存入栈中
git stash save "注释" # 类似于git stash,但是可是注释
git stash list # 列出栈
git stash show # 显示栈中的代码和工作区的区别
git stash pop # 把栈中的代码恢复到工作区,并清除栈
git stash apply # 把栈中的代码恢复到工作区,但是不清除栈
git stash clear # 清除所有的栈
git stash drop + 名称 # 删除一个栈
提交
====
git commit # git会调用vim来让你输入信息,适合较多信息输入的场合
git commit -a 指的是把当前工作目录中没有被git add添加的文件也提交到本地仓库,不推荐这个选项,应该先git add -A在git commit [-m]
删除指定提交
===========
假设你有c1~c5五个提交,你要删除c5这个提交
git log --oneline
eb6a3dd (HEAD -> master) c5
234ad32 c4
269f234 c3
bad34cd c2
245cf8c c1
git rebase -i <245cf8c> # git要指定一个起点的,这里以c1为起点,你也可以以其它为起点
# 此时弹出vim编辑器,内容大致是:开头几行字描述着各个提交该保留还是删除,下面的字讲的是所有可用的操作是什么意思
pick bad34cd c2
pick 269f234 c3
pick 234ad32 c4
pick eb6a3dd c5
# balabalabalabalabalabalabalabala
# balabalabalabalabalabalabalabala
# balabalabalabalabalabalabalabala
# 你想删除c5提交,只需把c5前面的pick改成drop即可。更改之后如下:
pick bad34cd c2
pick 269f234 c3
pick 234ad32 c4
drop eb6a3dd c5
# balabalabalabalabalabalabalabala
# balabalabalabalabalabalabalabala
# balabalabalabalabalabalabalabala
# vim保存退出即可
# 注意:
* 这个命令还有另外一个功效:它可以删除那种没有任何分支指向的提交,方法是你git rebase -i <...> 以后弹出的vim编辑器什么都不改,直接退出
* 这个命令还有其他功能,比如压缩提交,修改提交信息等,具体请看输入git rebase后的那个弹窗
* 如果遇到冲突,有三种操作:
* 放弃rebase:git rebase --abort
* 跳过此次rebase:git rebase --skip
* 合并冲突:(编辑冲突文件),然后git add <冲突文件>,然后git rebase --continue
* 编辑冲突文件时你会看到你之前的文件变成了类似下面这样:
1111
aaaa
++<<<<<<< HEAD
++=======
+ bbbb
+ dddd
++>>>>>>> 1a91894... V4
这上面,只有开头两行是你的。
"++<<<<<<< HEAD"意思是这个符号上面的就是你原本的;
"++>>>>>>> <提交SHA1> <提交信息>"意思是这行前面直到"++======="是你之前要做的改动;
那些以"+"开头的内容得删掉,不然待会git rebase --continue它们会进到追踪库里。改好这个文件后git add <刚刚你改的文件>,然后git git rebase --continue就行了
分支
====
git checkout -b <新的branch> # 创建一个新的分支,然后立马切过去
git branch -d <要删除的分支名字> # 删除本地分支
git push origin --delete <要删除的分支名字> # 删除远程分支。注意:<要删除的分支名字> 是直接写名字的,比如remotes/origin/bugfix这个分支你只要写bugfix就行了
git branch -f <分支名>
合并
====
git merge -e --no-ff # -e 合并后可以先看一下改了哪些再提交;--no-ff 不使用fast-forward合并策略,虽然git默认使用这种策略,但是
# 不推荐,应为这种策略合并后不会创建新的节点
合并一个分支上的某个文件
======================
有时候你只想合并一个分支上的某个文件到主线上来。
注意这个命令并不是真的合并,它只是把合并来的内容写到worktree里面!!!
git checkeout master # 先切到主线分支
git checkout -p deve ccc.txt # "deve ccc.txt"指的是你想合并deve分支上的ccc.txt文件
# 然后就会出现类似下面这种提示,你可以选择要不要合并
# 我在这里输入了个"?"让它打印出y,n,q,a,d,e的意思,一般就用y和n就够了
--- b/ccc.txt
+++ a/ccc.txt
@@ -1 +1,2 @@
333
+333-333-3333
Apply this hunk to index and worktree [y,n,q,a,d,e,?]? ?
y - apply this hunk to index and worktree
n - do not apply this hunk to index and worktree
q - quit; do not apply this hunk or any of the remaining ones
a - apply this hunk and all later hunks in the file
d - do not apply this hunk or any of the later hunks in the file
e - manually edit the current hunk
? - print help
删除未被跟踪的文件,delete untracked files
==========================================
# 删除 untracked files
git clean -f
# 连 untracked 的目录也一起删掉
git clean -fd
# 连 gitignore 的untrack 文件/目录也一起删掉 (慎用,一般这个是用来删掉编译出来的 .o之类的文件用的)
git clean -xfd
# 在用上述 git clean 前,强烈建议加上 -n 参数来先看看会删掉哪些文件,防止重要文件被误删
git clean -nxfd
git clean -nf
git clean -nfd
删除已经加入跟踪的文件
====================
# 比如.cproject这个文件已经加入版本跟踪系统了,你想把它从版本跟踪系统中移除
git rm -nr --cached .cproject # -n:这只是看而已,实际并不移除;-r:递归移除;--cached:从跟踪系统中移除,但仍保留在文件系统中
注意:
* 只要有“-n”这个参数就不会删除,只是打印出哪些文件会被删除而已,你如果真的十分确定删除了就去掉这个选项
* 关于“.gitignore”失效的问题,“.gitignore”只能忽略未被跟踪的文件,假如有个文件先被加入跟踪了你才用“.gitignore”忽略它,那么“.gitignore”将失效。解决办法是:用git rm把那个文件取消跟踪,再git add -A
查看已跟踪的所有文件
==================
git ls-files # 列出所有已跟踪文件
git ls-tree <分支名> --name-only # 这个好像是列出working space中的所有文件,不建议用这个
推送
===
git push origin master # 推送本地的master分支
git push origin bugfix:bugfix # 推送本地的bugfix分支(冒号前面)到远程的bugfix分支(冒号后面),如果远程不存在bugfix分支会自动创建;注意冒号两边不能有空格
git push origin --tags # 推送本地的所有标签
git push origin --all # 推送本地的所有分支
git push -u origin develop # 在远程创建一个新分支develop
git push -u origin master -f # 强制推送,可以解决"hint: Updates were rejected because the tip of your current branch is behind"问题
其他
====
git config --global core.editor "vim" # 把默认的编辑器改为vim
正则表达式
==========
* 正则表达式 [^a] 指的是匹配非a的字符串,[^abc] 匹配的是非a且非b且非c的字符串,val\s*=[^=] 匹配的是val=后面不是=的字符串
* 正则表达式各种语言都有内嵌,标准各有不同,有时同一个正则表达式在不同的语言环境中会有不同的匹配结果。ps:VIM的正则表达式就跟GNU的grep不同
正则表达式的一些例子:
=====================
(typedef|#define).*uint8_t --- typedef或者#define的后面跟上uint8_t
(?<=\bVERSION\b).* --- 匹配#define VERSION 123中的123。注意(?<=xxx)中的xxx必须是定长的,使用GNU的grep要加-P选项,其他的正则表达式不一定支持
aaa\s*=[^=\r\n] --- 匹配aaa后面带"="而不是"=="的字符串,也就是aaa这个变量的赋值语句
SHELL脚本
=========
查看文件系统类型
===============
df -T
parted -l
blkid
lsblk -f
查看内核符号表
==============
cat /proc/kallsyms
浮点运算
========
echo | awk '{printf("%.3f\n", 34/0.459834)}'
echo 'scale=3;34/0.459834' | bc # "scale=3;"的意思是小数点后面有3位
获取ASCII码
$ xxd
$ <直接输入你想要转换的字符,可以输入多个>
$ ctrl+d
打补丁
======
注意这是unix的diff,不是git diff
$ diff -nrNp <目录1> <目录2> > diff.patch # 生成目录2基于目录1的补丁
$ cd <目录1> # 打补丁前要进入目录1
$ patch -p1 < ../diff.patch # 打补丁,使目录1变得跟目录2一样
日期转秒
=======
date -d "2012-11-12 13:00:00" +"%s"
秒转日期
=======
date -d@1352692800 +"%Y-%m-%d %H:%M:%S"
同时移动或拷贝多个文件
====================
mv {a.c,b.c,c.c} folder # 把mv换成cp就是拷贝
写入二进制数据到文件
==================
echo -e "\x01\x02" > 111.bin
读取二进制文件
===============
使用xxd命令
===========
xxd -g {m} -c {n} {文件名} # 其中m是一个单元字节;n是一行几个单元
例如:
xxd -g 1 -c 8 README.txt
延伸:
这个命令可以被VIM调用:
%!xxd -g 1 -c 8
使用od命令
==========
od -t xC -A [doxn] -N [num] -w<列数> <文件名>
-t 指定格式
x 16进制格式
C 字节格式
-w 一行显示几列
doxn d:十进制;o:八进制;x:十六进制;n:不显示地址
-N[num] 显示num个单位
od --traditional -d
--traditional 以传统方式接受参数(od可以以好几种方式接受参数)
-d 每两个字节组成一个十进制数
举例:
od -t xC -A n -N 80 -w8 ECG_Datas.dat # 以char为单位(-t xC),不显示地址(-A n),总共显示80个单位(-N 80),一行8个单位(-w8)
文本替换命令
============
sed -i 's/idata//g' Mifare.c # 把Mifare.c中的idata全部去掉
# find命令
find . ! -name 'port.h' # 查找不是port.h的文件
find . -regex ".*dat" # 查找当前目录下的所有.dat文件,注意使用-regex(正则表达式)以后,匹配的不只是文件名
而是绝对路径
find . \( ! -name "*.dat" \) -a \( ! -name "*.sh" \) # 当前目录找不是.dat也不是.sh文件的文件
find . \( \( -name foo.c \) -o \( -name main.c \) \) -printf "${PWD}/%P size=%sByte\n" # 找main.c和foo.c并打印出它们的绝对路径和大小
shell的延时
===========
sleep : 默认为秒。
sleep 1s 表示延迟一秒
sleep 1m 表示延迟一分钟
sleep 1h 表示延迟一小时
sleep 1d 表示延迟一天
usleep表示微秒
date命令
========
tm=`date --date="1 hour ago" +%Y%m%d%H%M` # 获取当前时间的一小时以前的时间
echo $tm
tm=`date --date="20181009 1045 1 hour ago" +%Y%m%d%H%M` # 获取指定时间一小时以前的时间
echo $tm
把字符串写入文件
================
如果字符串只有一行
==================
这不难
echo "111 222" > a.txt
或者这样:
for line in "111 222"
do
echo $line >> a.txt
done
如果字符串有多行
================
这个知识点很隐蔽,因为刚学这个的人肯定会以为可以像处理单行字符串那样,不行的。
用cat:
text="line 1
line 2
line 3"
cat>$file<
EOF
字符串去重
=========
sort -u # 去除重复只保留一个然后排序
uniq # 只去除连续的重复
引申
====
ls -R | grep -oE '\.[0-9a-zA-Z_\.]+$' | sort -u # 列出一个目录下的所有文件类型
列出一个目录下的全部文件
======================
ls -lR | grep -E "^-" | grep -oE ":\w\w .*$" | grep -oE " .*$"
grep
====
grep -nrE --include=*.{c,h} "mf_" # -n:打印行号;-r:递归查找;-E:正则表达式;--include=*.{c,h}:去.c和.h文件里面找;"mf_":以mf_开头的东西
文本编辑命令
============
awk -F" " '{print NF}' read.txt
-F" " 指定分隔符是空格
'{print NF}' 打印每一行的列数
cat yy.txt | awk '{printf "%-30s%-15s\n",$1,$2}' > yy2.txt
把yy.txt中的第一第二列按固定的缩进打印并输出到yy2.txt
# %-30s表示输出字符串,宽度30位,左对齐.%-15s用来指定第二列的,左
# 对齐,宽度15.两个百分号之间可以没有空格.使用\n对每一行的输出加上换行符
# 如果要表示第10列及以上,用$(10),$(11)...
清空一个文件
===========
cat /dev/null > dat.bin
C语言
===================
结构体也可以这样定义
==================
struct AAA {
int a;
int b;
} k = {
a: 123,
b: 456,
};
关于typedef
===========
typedef double fftw_complex[2];
fftw_complex a; // a是一个由两个double型组成的数组
fftw_complex *b; // b是一个指向数组的指针,改数组由两个double型组成
用宏定义把数字转成字符串
======================
/*
* 如果#define SAMPLE_RATE (16000)就不灵了
*/
#define SAMPLE_RATE 16000
#define STR1(R) #R
#define STR2(R) STR1(R)
int main()
{
printf(STR1(SAMPLE_RATE) "\n"); /* SAMPLE_RATE */
printf(STR2(SAMPLE_RATE) "\n"); /* 16000 */
return 0;
}
指向数组的指针
=============
int main() {
const char *p= "12345678";
char (*q)[2] = (char (*)[2])p;
printf("%c%c\n", q[0][0], q[0][1]);
printf("%c%c\n", q[1][0], q[1][1]);
return 0;
}
库函数获取毫秒
==============
#include
#include
long long getSystemTime() {
struct timeb t;
ftime(&t);
return 1000 * t.time + t.millitm;
}
int main() {
long long start=getSystemTime();
sleep(5);
long long end=getSystemTime();
printf("time: %lld ms\n", end-start);
return 0;
}
库函数延时函数
===================
sleep() 秒延时
usleep() 微秒延时
scanf用法
========
#include
void main() {
int num, hour, min, sec;
printf("num=");
scanf("%d", &num);
hour = num / 3600;
min = num % 3600 / 60;
sec = num % 60;
printf("%d 小时 %d 分钟 %d 秒\n", hour, min, sec);
}
判断闰年
=======
公历闰年判定遵循的规律为: 四年一闰,百年不闰,四百年再闰。
公历闰年的简单计算方法(符合以下条件之一的年份即为闰年)
1.能被4整除而不能被100整除。
2.能被100整除也能被400整除。
闰年是公历中的名词。闰年分为普通闰年和世纪闰年。
普通闰年:能被4整除但不能被100整除的年份为普通闰年。(如2004年就是闰年,1999年不是闰年);
世纪闰年:能被400整除的为世纪闰年。(如2000年是世纪闰年,1900年不是世纪闰年)。
指向数组的指针
=============
char a[30] = "123";
char (*p)[30] = &a;
printf("p=%p, a=%p\n", p, a); // p == a
知识点
=====
* 上面的代码中,如果p++,p的地址一次加30
* char (*p)[30] = &a; 指向数组的指针就是这样赋值的,&a其实是等于a的
编程坑点
=========
* 取局部变量的地址要注意内存释放的问题。当你使用局部变量的地址引用局部变量时,局部变量可能早就被释放了,所以
如果非要,记得局部变量加volatile
* 内存、中断、电压(低功耗)是全局的,任何一个函数都要考虑这三个方面
* 要有错误处理(日志,打印等)程序,switch和if要做好default和else的检查,空的else最好用/*nothing here*/注明
* 小心函数的重复运行问题,比如task_create反复执行会创建出很多个一样的任务。另外,中断也是可以打断中断的,也是函数的重复运行问题
* 全局变量和硬件如果被多任务,中断共享要做好保护措施
* 系统的初始化也有学问,注意系统的各个软硬件的初始化顺序
* 小心死锁问题,死锁也能导致死机,发生原因一般是嵌套锁
* 建议加看门狗,小心看门狗初始化失败时可能仍然生效,如果此时你认为看门狗初始化失败而不喂狗那么软件就会一直复位
* 测试代码的时候要记录栈使用情况,防止栈溢出
* 小心C语言的宏定义,比如这个:#define SET_MODE(hd, mode) led_handles[(hd)].mode = (mode)
当你这样调用时:SET_MODE(1, sta),展开成了led_handles[(hd)].sta = sta,你本想改变mode成员,结果改到sta成员去了
* 拷贝大的全局变量时要注意共享问题
* 大坑:把一个局部变量定义成const仍是局部变量,仍是放在栈里面的!!!
* 小心float和double的精度问题
* DMA访问内存不会更新Cache(可能还有别的类似的硬件),所以它可以导致Cache和实际内存不一致,所以DMA读写内存前后要做好Cache的同步措施
* 小心字符串末尾的零。如果一个字符串末尾没有零,那么strcpy这种函数将是灾难性的
* &(按位与)的优先级比+,-还低
* 中断过于频繁地执行会导致程序卡慢甚至完全卡死,所以程序要限制中断的执行频率
* 用完的指针,句柄,ID等应当置为一个无效值,比如0,避免后面的代码误认为它仍然有效
* 小心,不要去访问已经被释放掉的内存
* 有些编译器,函数只声明,不定义,编译是通过的。这可能有问题
* 小心父进程比子进程先退出
不安全的C库函数
==============
#ifndef BANNED_H
#define BANNED_H
/*
* This header lists functions that have been banned from our code base,
* because they're too easy to misuse (and even if used correctly,
* complicate audits). Including this header turns them into compile-time
* errors.
*/
#define BANNED(func) sorry_##func##_is_a_banned_function
#undef strcpy
#define strcpy(x,y) BANNED(strcpy)
#undef strcat
#define strcat(x,y) BANNED(strcat)
#undef strncpy
#define strncpy(x,y,n) BANNED(strncpy)
#undef strncat
#define strncat(x,y,n) BANNED(strncat)
#undef sprintf
#undef vsprintf
#ifdef HAVE_VARIADIC_MACROS
#define sprintf(...) BANNED(sprintf)
#define vsprintf(...) BANNED(vsprintf)
#else
#define sprintf(buf,fmt,arg) BANNED(sprintf)
#define vsprintf(buf,fmt,arg) BANNED(sprintf)
#endif
#endif /* BANNED_H */
PYTHON
======
编程例子:
=========
打印字母A到Z:
for i in range(ord('A'), ord('Z')):
print(chr(i))
emWin
=======
MESSAGEBOX_Create, GUI_MessageBox都是创建消息框函数,区别是前者能重写回调函数(但是回调函数只接
受WM_PAINT这一个消息),后者不能
STM32HAL库
==========
怎样初始化一个外设
==================
以串口3为例:
1. 定义一个串口3的全局句柄USART_HandleTypeDef xxx,后续所有的操作都要用到它
2. stm32f7xx_hal_msp.c文件的HAL_USART_MspDeInit函数添加串口3的默认初始化函数,一般是关时钟,中断和GPIO默认初始化
3. stm32f7xx_hal_msp.c文件的HAL_USART_MspInit函数添加串口3外围的初始化函数,包括串口3的时钟和相应的GPIO时钟使能,
GPIO初始化,串口3的中断初始化
4. main.c或者其他哪个文件都行,写一个串口3真正的初始化函数,包括波特率,校验位那些
怎样使用一个中断
================
以串口3为例:
1. stm32f7xx_it.c文件添加USART3_IRQHandler函数
2. 重写HAL_UART_XXXtCallback函数
3. 使用HAL_UART_Receive_IT函数注册中断接收数组
4. 别忘了在HAL_UART_MspInit中使能串口中断
其他
====
* HAL库的头文件只需一个#include "stm32f7xx_hal.h"即可
* 小心DMA,例如你在一个DMA传输函数执行结束后读取内存,这个内存可能仍被DMA控制
Keil MDK
========
生成bin文件
===========
$K\ARM\ARMCC\bin\fromelf.exe --bin [email protected] !L # 在工程目录下生成bin文件
或者
$K\ARM\ARMCC\bin\fromelf.exe --bin --output=Bin\@L.bin !L # 在工程目录下的Bin文件夹生成bin文件
重写函数
=======
int $Sub$$main(void)
{
__nop();
$Super$$main();
}
知识点:
* 上面的代码中,$Sub$${函数名}是重写一个函数的意思,$Super$${函数名}是原来的函数的意思(你如果想调用以前的函数就必须得加这个开头$Super$$)。不止于main函数,什么函数都可以这样
* 利用这个功能,你可以在main函数之前做点其他的代码,比如初始化
怎样重定向printf
===============
1. 添加段代码
============
#include
int fputc(int ch, FILE *f)
{
uint8_t temp[1] = {ch};
HAL_UART_Transmit(&huart1, temp, 1, 2);
return(ch);
}
2. USE Micro Lib
================
点击魔术棒,找到这项勾上
GCC
====
生成so文件
=========
使用"-fPIC -shared",举例:gcc test.c -fPIC -shared -o libtest.so
编译时指定so搜索目录
==================
格式:"-Wl,-rpath,/the/search/dir",举例:gcc ... -Wl,-rpath,/root/test/lib -o ...
指定多个so搜索目录:-Wl,-rpath,/the/search/dir1,-rpath,/the/search/dir2
小心cygwin的GCC和Linux的GCC在使用so时不一定是相同的。
生成a文件
========
使用ar命令把o文件生成a文件
$ gcc -c foo.c -o foo.o
$ ar r foo.a foo.o [foo2.o foo3.o ...]
重定向printf
============
可以参考ST的CubeMX生成代码,以后再写笔记
链接
====
链接并不是只能用LD,GCC也可以,有时甚至链接只能用GCC
================================================
把一个变量放到指定的段内
=========================
__attribute__((section("name"))) # name即是你要指定的段,名字随便取,可以带'.'号
例如:
int david __attribute__((section(".user.char.1"))) = 0x123; # 把david这个变量放到".user.char.1"段中
利用链接脚本导出符号
====================
在C语言里面,你若想导出一个符号,必然要用extern。但是GCC的链接脚本允许你不用那种方法:
# 链接脚本中定义好".user.char.1"段
SECTIONS
{
.text :
{
...
*(.user.char.1)
...
}
}
# C工程中定义一个位于".user.char.1"段的变量
int david __attribute__((section(".user.char.1"))) = 0x123;
# 此时david这个变量就变成全局变量了,你可以在工程的任意一个位置访问它而不需要extern。
# 实际上,你还可以把链接脚本改成这样:
SECTIONS
{
.text :
{
...
user_start = .;
*(.user.char.1)
*(.user.char.2)
*(.user.char.3)
*(.user.char.4)
user_end = .;
...
}
}
# 这种情况适用于当你的自定义段很多的时候,你可以通过获取user_start和user_end的地
# 址(即&user_start, &user_end)来访问到这个“数组”。Linux内核里面有大量应用
GDB
===
x/32xb buf # 查看buf内存
info locals # 查看局部变量
ubuntu,树莓派,安卓
===================
安装eclipse
===========
apt-get install eclipse-platform # eclipse-platform和eclipse不同,前者没有任何语言开发插件;后者带有JAVA开发插件
apt-get install eclipse-cdt # 安装C/C++的开发插件
想用新版eclipse只能手动安装。新一点的ubuntu应该都是可以的,我在ubuntu12上安装的时候,明明JRE是1.8版本,但是eclipse说它是
1.6版本,跑不起来。
卸载软件
=======
sudo apt-get remove xfce4* # 把xfce4*改成你要卸载的软件
sudo apt-get autoremove
sudo apt-get clean
查看ubuntu版本
=============
lsb_release -a
开启和关闭ubuntu桌面
==================
sudo service lightdm stop # 临时关闭
sudo service lightdm start # 临时开启
sudo systemctl set-default multi-user.target # 永久关闭
sudo systemctl set-default graphical.target # 永久开启
安装桌面
========
lxde: sudo apt-get install lxde
xfce: sudo apt-get install xfce4
有些桌面一旦安装好,重启电脑即可看到,如果没有,使用命令startx启动桌面,使用pkill Xorg关闭
桌面(先用ctrl+alt+F2切到另一个SSH)
树莓派技巧
==========
用SD卡开启SSH(仅适用于官方系统):在SD卡根目录新建一个空文件SSH
用SD卡配置WIFI(仅适用于官方系统):在SD卡根目录新建wpa_supplicant.conf文件,填入
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
network={
ssid="你的WIFI名"
psk="WIFI密码"
}
查看系统是多少位
===============
getconf LONG_BIT
su失败的解决办法
================
问题:
pi@raspberrypi:/ $ su
密码:
su:鉴定故障
解决办法:
sudo su
开启SSH服务
==========
ubuntu默认是不使能SSH的,你得自己安装配置(树莓派是安装了SSH的,只是没有使能)
sudo apt-get install openssh-server
sudo systemctl restart ssh
其他:
当你用ssh登录的时候会发现终端变成黑白的,那是因为ubuntu默认就是关闭ssh的彩色显示的。这时你可以编辑~/.bashrc文件,把force_color_prompt赋值yes即可
挂载U盘
=======
$ cat /proc/partitions # 或者lsblk
major minor #blocks name
8 0 62522712 sda
8 1 524288 sda1
8 2 60996608 sda2
8 3 1000448 sda3
8 16 31326208 sdb # 这是U盘
8 17 31326176 sdb1 # 这是U盘的分区
$ sudo mount /dev/sdb1 /mnt
$ sudo umount /mnt # 或者 sudo umount /dev/sdb1
udev语法简单讲解
===============
用户配置目录位于/etc/udev/rules.d/中,系统预置位于/lib/udev/rules.d/中。文件名必须以.rules结尾。
rules文件由一系列的规则组成,每个规则又由一系列键值对组成。一个规则就是一行,如果一个规则包含多个键值对,则各个键值对之间要用逗号隔开。
键值对的逻辑有点像C语言的if else。简单说就是,如果第一个键值对使用了==且成立,那么该规则后面的所有键值对就得以执行,其他诸如!=亦是同理。
举例:(这是网上截取别人的,并不好用)
####################################################################################
1 KERNEL!="sd[b-z]*", GOTO="exit"
2 ACTION=="add", PROGRAM!="/sbin/blkid %N", GOTO="exit"
3
4 # import some useful filesystem info as variables
5 IMPORT{program}="/sbin/blkid -o udev -p %N"
6
7 # get the label if present, otherwise assign one based on device/partition
8 ENV{ID_FS_LABEL}!="", ENV{dir_name}="%E{ID_FS_LABEL}"
9 ENV{ID_FS_LABEL}=="", ENV{dir_name}="flash_drive_%k"
10
11 # create the dir in /media and symlink it to /mnt
12 ACTION=="add", RUN+="/bin/mkdir -p '/media/%E{dir_name}'"
13
14 LABEL="exit"
####################################################################################
1. 如果设备名不等于sd[b-z]*,那就跳到exit标签,也就是退出整个rules文件。KERNEL是设备的内核名称,%k是它的简写。
2. 如果第1行成立,那么如果设备是插入,那就执行"/sbin/blkid %N", GOTO="exit"。PROGRAM!=的意思是需要检查返回值。
5. 把"/sbin/blkid -o udev -p %N"的执行结果导入program这个变量。%N是设备节点的名称(也就是设备文件的名称)。
8. 如果ID_FS_LABEL这个环境变量非空,那么把变量ID_FS_LABEL赋给dir_name。%E{*}等价于ENV{*},就是取某个环境变量的意思。
9. 和第8行很类似,不同的是dir_name被赋值为flash_drive_%k。%k是设备的内核名称,比如/dev/sdb1
12. 如果是插入动作则执行"/bin/mkdir -p '/media/%E{dir_name}'"。
14. 一个标签,跟C语言的标签是一个意思。
# udev的语法太复杂,自己写的话要是写不好可能会导致系统崩溃,所以建议安装XFCE等桌面应用来实现U盘自动挂载
udev自动挂载U盘和SD卡
====================
这是一个简单的udev挂载U盘的rules文件,使用时注意/etc/udev/rules.d/99-mount-sam.rules中的sd[b-z],它不支持名为sda的设备,因为
sda一般是系统硬盘,一旦这个rules文件挂载了系统硬盘可能会使整个系统崩溃。所以,在使用前要看系统本身的硬盘是什么,然后修改这个文件,使
这个文件不会动系统硬盘。
$ sudo vim /etc/udev/rules.d/99-mount-sam.rules # 以99开头是因为我想让系统的rules文件先执行
ACTION=="add", KERNEL=="sd[b-z][0-9]", RUN+="/home/sam/.mount.sh %k"
ACTION=="remove", SUBSYSTEM=="block", KERNEL=="sd[b-z][0-9]", RUN+="/home/sam/.umount.sh %k"
$ vim /home/sam/.mount.sh
#!/bin/sh
# if the device had been mounted already, no need to mount again
df | grep -E "^/dev/$1" 1>/dev/null 2>&1
if [ $? -eq 0 ]; then
exit
fi
mkdir -p /mnt/$1
mount /dev/$1 /mnt/$1
sync
$ vim /home/sam/.umount.sh
#!/bin/sh
umount /mnt/$1
rmdir /mnt/$1
sync
$ chmod +x /home/sam/.mount.sh /home/sam/.umount.sh
$ /etc/init.d/udev restart
一些Ubuntu软件源
===============
# 阿里云源
deb http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-backports main restricted universe multiverse
##測試版源
deb http://mirrors.aliyun.com/ubuntu/ trusty-proposed main restricted universe multiverse
# 源碼
deb-src http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-backports main restricted universe multiverse
##測試版源
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-proposed main restricted universe multiverse
# 清华大学源
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ trusty main restricted universe multiverse
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ trusty-security main restricted universe multiverse
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ trusty-updates main restricted universe multiverse
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ trusty-backports main restricted universe multiverse
##測試版源
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ trusty-proposed main restricted universe multiverse
# 源碼
deb-src http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ trusty main restricted universe multiverse
deb-src http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ trusty-security main restricted universe multiverse
deb-src http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ trusty-updates main restricted universe multiverse
deb-src http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ trusty-backports main restricted universe multiverse
##測試版源
deb-src http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ trusty-proposed main restricted universe multiverse
树莓派改软件源
=============
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
sudo vi /etc/apt/sources.list
把以前的都删掉,加入deb http://mirrors.ustc.edu.cn/raspbian/raspbian/ stretch main contrib non-free rpi
保存退出
sudo cp /etc/apt/sources.list.d/raspi.list /etc/apt/sources.list.d/raspi.list.bak
sudo vi /etc/apt/sources.list.d/raspi.list
把以前都删了,加入deb http://mirrors.ustc.edu.cn/archive.raspberrypi.org/debian/ stretch main ui
保存退出
sudo su
apt-get update && apt-get upgrade
ubuntu改软件源
=============
1. 改source.list文件
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
sudo vi /etc/apt/sources.list
# 把上文的“清华大学源”或者“阿里云源”填入/etc/apt/sources.list
# 把文件中的“trusty”改成你自己的ubuntu代号,这个代号通过“lsb_release -a”获取
或者:
去中科大的官网下载一个sources.list文件(可以输入"ubuntu"查找),复制里面的内容到/etc/apt/sources.list就行了。
这个方法也不推荐,因为中科大的source.list屏蔽了一些东西,会导致一些问题。
或者:
sudo sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
这个方法简单粗暴,但不推荐,会导致一些问题。
2. 更新
sudo apt-get update
sudo apt-get upgrade
查看有哪些设备连入了本设备的热点
=============================
ip neigh
搭建ftp服务器
============
ubuntu:
sudo apt-get install vsftpd
sudo vim /etc/vsftpd.conf
把#write_enable=YES改成write_enable=YES
保存退出
sudo service vsftpd restart # 当然用sudo systemctl restart vsftpd或者sudo /etc/init.d/vsftpd restart也可以
windows:
ftp://
账号:pi
密码:
结果:
ubuntu的/home/pi目录共享到了windows上。有关vsftp的所有配置都在/etc/vsftpd.conf文件中
你可以用man vsftpd或者man vsftpd.conf获取帮助
搭建samba服务器
==============
ubuntu:
sudo apt-get update
sudo apt-get install samba samba-common-bin
sudo vim /etc/samba/smb.conf
# 在文件的最底部添加这段代码。注意"="两边可以带空格;好像不可以用tab来当空格
[pi] # "pi"你可以换成自己的名字
path = /home/pi # 共享目录
writable = yes
readonly = no # 允许读写;yes是只读
public = yes
保存退出
sudo chmod -R 7777 /home/pi # 7777中第1个7的意思是uid,gid和粘滞位都是1
sudo smbpasswd -a pi # 往samba中添加用户pi,系统会提示输入密码。注意这个用户必须是ubuntu真实存在的用户,你可能需要user add pi
sudo service smbd restart # 当然用sudo systemctl restart smbd或者sudo /etc/init.d/smbd restart也可以
windows:
文件管理器找到"网络>>RASPBERRYPI>>pi",输入账号pi以及他的密码即可
搭建nfs服务器
============
Windows挂载nfs非常卡,还不支持中文,不建议使用
ubuntu:
sudo apt-get install nfs-kernel-server # 这步你可能并不需要,因为很多Linux发行版都是自带nfs的。你可以先看看/etc/export是否存在,如果存在则说明安装了
sudo vim /etc/exports
末尾添加这个
/home/pi *(rw) # "/home/pi"是你要共享出去的路径;"*"指的是任何网段的主机都可以访问你的nfs;"(rw)"指的是别人可读可写
保存退出
chmod 777 /home/pi
sudo systemctl restart nfs-kernel-server.service # 当然你用sudo service <服务名> restart或者sudo /etc/init.d/<服务名> restart也可以
windows:
控制面板--->程序--->打开或关闭Windows功能。把NFS服务子项全部勾选,"基于UNIX的应用程序子系统"勾选
cmd窗口输入:mount \\192.168.43.254\home\pi x: 或者 文件管理器--->映射网络驱动器--->填入\\192.168.43.254\home\pi--->确定
打开文件浏览器,你可以看到ubuntu的nfs挂载上来了,但是是只读的,尽管你的ubuntu已经规定可写了,网上有解决办法,但是我试了不成功
如果卸载挂载,cmd窗口输入:umount -a -f
搭建tftp服务器
=============
$ sudo apt-get install xinetd tftp tftpd
$ vi /etc/xinetd.d/tftp
service tftp
{
socket_type = dgram
protocol = udp
wait = yes
user = root
server = /usr/sbin/in.tftpd
server_args = -s /home/sam/Work/tftp_share
disable = no
per_source = 11
cps = 100 2
flags = IPv4
}
$ mkdir /home/sam/Work/tftp_share
$ chmod 777 /home/sam/Work/tftp_share
$ sudo /etc/init.d/xinetd restart
eclipse
========
* 在Windows下,当你用eclipse编译c代码时,工具链(gcc,gdb,make等)得自己准备,网上工具链一大把,推荐使用Qt自带的MinGW,别用CodeBlocks的MinGW,虽然它更全,但是在eclipse下不能正常工作。
* eclipse在设置工具链时有时不能马上见效,可以删除工程,删除文件系统里的.settings,.project,.cproject文件再重新创建工程
zsh美化
========
Linux一般使用bash作为SHELL,但除了bash,还有个zsh,ohmyzsh就是一个美化zsh的软件
安装
====
1.
sudo apt-get install zsh
sudo chsh -s $(which zsh)
2.
有了zsh,你还得安装它的配置文件,这样终端才会五彩斑斓起来。这个配置文件最流行的就是"Oh My Zsh":
sh -c "$(wget -O- https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
有时,这个命令并不管用,你可以试试这个:
git clone https://github.com/ohmyzsh/ohmyzsh.git
./ohmyzsh/tools/install.sh # 小心这步执行到一半会让你输入密码(如果你选择了把zsh作为默认shell的话),如果你输错密码就得执行uninstall.sh重来
bash美化
=======
类似于zsh,bash也有美化软件。如果你不适应zsh的语法,又不喜欢bash默认的配色,可以试试使用bash美化软件,oh-my-bash就是其中之一。
地址:https://github.com/ohmybash/oh-my-bash.git。使用跟ohmyzsh很类似。
使用官网推荐的curl和wget经常无效,所以推荐手动安装:
git clone git://github.com/ohmybash/oh-my-bash.git ~/.oh-my-bash
cp ~/.bashrc ~/.bashrc.orig
cp ~/.oh-my-bash/templates/bashrc.osh-template ~/.bashrc
# 然后你根据自己的需要编辑~/.bashrc
source ~/.bashrc
# 我发现这个软件有些主题显示的时间是12小时,很不习惯,可以这样改:
# vim ~/.oh-my-bash/themes/candy/candy.theme.sh
# THEME_CLOCK_FORMAT="%H:%M:%S" # 把原来的THEME_CLOCK_FORMAT赋值语句删除,添加这句
设置网络
=======
nmtui 字符GUI工具,进去以后你自然懂得怎么用。推荐
nm-connection-editor 图形GUI工具,进去以后你自然懂得怎么用。在没有桌面环境和x-windows的系统中没法用
nmcli 纯字符工具,操作超级复杂,不记了
ifconfig 纯字符工具,操作比较复杂,不记了
查找一个软件在哪个包
==================
apt-cache search xxx # 只是列出一些跟xxx相关的软件,具体要哪个还得你自己定
设置时区
=======
sudo cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
终端分屏工具terminator
======================
$ sudo apt-get install terminator
$ terminator
ctrl+shift+o 水平分割
ctrl+shift+e 垂直分割
ctrl+shift+上下左右 调整窗口大小
ctrl+tab 切换窗口
ctrl+shift+w 关闭窗口
MobaXterm
==========
解决有时X11启动不来的问题:
1. 使用Ubuntu默认用户登录
2. cp /home/<能用X11的用户>/.Xauthority /home/<不能用X11的用户>/.Xauthority