PCB

Process Control Block

它放在RAM(运行内存)里并包含着进程的信息。每个进程都把自己的信息放在task_struct数据结构里。

Take kernel 4.14 as example.

从这时候发现,还是Chinese更亲切

task_struct 结构体定义在

sched.h

5.X的内核又改了,task_struct 位置不在这个头文件里

##调度数据成员##

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
(1) volatile long states;
表示进程的当前状态:

TASK_RUNNING:正在运行或在就绪队列run-queue中准备运行的进程,实际参与进程调度。
TASK_INTERRUPTIBLE:处于等待队列中的进程,待资源有效时唤醒,也可由其它进程通过信号(signal)或定时中断唤醒后进入就绪队列run-queue。
TASK_UNINTERRUPTIBLE:处于等待队列中的进程,待资源有效时唤醒,不可由其它进程通过信号(signal)或定时中断唤醒。
TASK_ZOMBIE:表示进程结束但尚未消亡的一种状态(僵死状态)。此时,进程已经结束运行且释放大部分资源,但尚未释放进程控制块。
TASK_STOPPED:进程被暂停,通过其它进程的信号才能唤醒。导致这种状态的原因有二,或者是对收到SIGSTOP、SIGSTP、SIGTTIN或SIGTTOU信号的反应,或者是受其它进程的ptrace系统调用的控制而暂时将CPU交给控制进程。
TASK_SWAPPING: 进程页面被交换出内存的进程。

Said by Kernel

/*
* Task state bitmask. NOTE! These bits are also encoded in fs/proc/array.c: get_task_state().
* We have two separate sets of flags: task->state is about runnability, while task->exit_state are
* about the task exiting. Confusing, but this way modifying one set can't modify the other one by
* mistake. */

(2) unsigned long flags;
进程标志:

?PF_ALIGNWARN 打印对齐警告信息。
?PF_PTRACED 被ptrace系统调用监控。
?PF_TRACESYS 正在跟踪。
?PF_FORKNOEXEC 进程刚创建,但还没执行。
?PF_SUPERPRIV 超级用户特权。
?PF_DUMPCORE dumped core。
?PF_SIGNALED 进程被信号(signal)杀出。
?PF_STARTING 进程正被创建。
?PF_EXITING 进程开始关闭。
?PF_USEDFPU 该进程使用FPU(SMP only)。
?PF_DTRACE delayed trace (used on m68k)。

(3) long priority;
进程优先级。 Priority的值给出进程每次获取CPU后可使用的时间(按jiffies计)。优先级可通过系统调用sys_setpriorty改变(在kernel/sys.c中)。

(4) unsigned long rt_priority;
rt_priority 给出实时进程的优先级,rt_priority+1000给出进程每次获取CPU后可使用的时间(同样按jiffies计)。实时进程的优先级可通过系统 调用sys_sched_setscheduler()改变(见kernel/sched.c)。

(5) long counter;
在 轮转法调度时表示进程当前还可运行多久。在进程开始运行是被赋为priority的值,以后每隔一个tick(时钟中断)递减1,减到0时引起新一轮调 度。重新调度将从run_queue队列选出counter值最大的就绪进程并给予CPU使用权,因此counter起到了进程的动态优先级的作用 (priority则是静态优先级)。

(6) unsigned long policy;
该进程的进程调度策略,可以通过系统调用sys_sched_setscheduler()更改(见kernel/sched.c)。调度策略有:
SCHED_OTHER 0 非实时进程,基于优先权的轮转法(round robin)。
SCHED_FIFO 1 实时进程,用先进先出算法。
SCHED_RR 2 实时进程,用基于优先权的轮转法。

#define SCHED_NORMAL 0
#define SCHED_FIFO 1
#define SCHED_RR 2
#define SCHED_BATCH 3
/* SCHED_ISO: reserved but not implemented yet */
#define SCHED_IDLE 5
#define SCHED_DEADLINE 6

Examples

list_PCBs.c

Web

OverView

https://www.w3school.com.cn/、https://www.runoob.com/https://www.sololearn.com/ 用来学习入门级的编程基础,是非常不错的。最推荐sololearn,尤其是英语一般的又希望英语也不落下的。

可惜的是 国内访问不了sololearn

Markdown

Markdown 支持许多HTML 5标签。—> 这和Markdown的解释器有关

Vincent 长庚

测试了下,支持article 和 aside 标签

博客系统

Apache (Web服务器)

apache和httpd是一个,到apache2后就叫httpd了。

NginX

Nginx(“engine x”)是一款开发高性能的Web和反向代理服务器,也是一个IMAP/POP3/SMTP代理服务器。

DOM

DOM

DOM

定义了访问 HTML 和 XML 文档的标准

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html>
<body>

<p id="intro">Helweelo World!</p>
<p id="me">本例演示 <b>getElementById</b> 方法!</p>

<script>
x=document.getElementById("me");
document.write("<p>来自 intro 段落的文本:" + x.innerHTML + "</p>");
</script>

</body>
</html>

方法 描述
getElementById() 返回带有指定 ID 的元素。
getElementsByTagName() 返回包含带有指定标签名称的所有元素的节点列表(集合/节点数组)。
getElementsByClassName() 返回包含带有指定类名的所有元素的节点列表。
appendChild() 把新的子节点添加到指定节点。
removeChild() 删除子节点。
replaceChild() 替换子节点。
insertBefore() 在指定的子节点前面插入新的子节点。
createAttribute() 创建属性节点。
createElement() 创建元素节点。
createTextNode() 创建文本节点。
getAttribute() 返回指定的属性值。
setAttribute() 把指定属性设置或修改为指定的值。

innerHTML 属性

innerHTML 属性可用于获取或改变任意 HTML 元素,包括 和 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html>
<body>

<p>Hello World!</p>
<p>DOM 很有用!</p>
<p>本例演示 <b>getElementsByTagName</b> 方法。</p>

<script>
x=document.getElementsByTagName("p");
document.write("第一段的文本: " + x[0].innerHTML);

document.write("第一段的文本: " + x[1].innerHTML);

document.write("第一段的文本: " + x[2].innerHTML);
</script>

</body>
</html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html>
<body>

<p>Hello World!</p>

<div id="main">
<p>DOM 很有用!</p>
<p>本例演示 <b>getElementsByTagName</b> 方法。</p>
</div>

<script>
x=document.getElementById("main").getElementsByTagName("p");
document.write("div 中的第一段的文本: " + x[0].innerHTML);
</script>

</body>
</html>

修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<html>
<body>

<p id="p1">Hello World!</p>
<p id="p2">Hello world!</p>

<script>
document.getElementById("p1").innerHTML="New text!";
</script>
<script>
document.getElementById("p2").style.color="blue";
</script>

<script>
var para=document.createElement("p");
var node=document.createTextNode("This is new.");
para.appendChild(node);

var element=document.getElementById("d1");
element.appendChild(para);
</script>

</body>
</html>

事件

1

导航

1

HTML5

  • HTML5 的<header>和html4的<head>标签是完全不一样的
  • article可以取代 div
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE html>
<html>
<body>
<p id="demo">点击这个按钮,获得您的坐标:</p>
<button onclick="getLocation()">试一下</button>
<script>
var x=document.getElementById("demo");
function getLocation()
{
if (navigator.geolocation)
{
navigator.geolocation.getCurrentPosition(showPosition);
}
else{x.innerHTML="Geolocation is not supported by this browser.";}
}
function showPosition(position)
{
x.innerHTML="Latitude: " + position.coords.latitude +
"<br />Longitude: " + position.coords.longitude;
}
</script>
</body>
</html>

CSS

JavaScript

BootStrap

CSS

GitBook

GitBook 是一个基于 Node.js 的命令行工具,可使用 Github/Git 和 Markdown 来制作精美的电子书

Learn JavaScript
How to Make an Operating System

GitBook入门

GitBook支持输出多种文档格式:

静态站点:GitBook默认输出该种格式,生成的静态站点可直接托管搭载Github Pages服务上;

PDF:需要安装gitbook-pdf依赖;

eBook:需要安装ebook-convert;

单HTML网页:支持将内容输出为单页的HTML,不过一般用在将电子书格式转换为PDF或eBook的中间过程;

JSON:一般用于电子书的调试或元数据提取。

使用GitBook制作电子书,必备两个文件:README.md和SUMMARY.md。

HTML

DOM

DOM

DOM

定义了访问 HTML 和 XML 文档的标准

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html>
<body>

<p id="intro">Helweelo World!</p>
<p id="me">本例演示 <b>getElementById</b> 方法!</p>

<script>
x=document.getElementById("me");
document.write("<p>来自 intro 段落的文本:" + x.innerHTML + "</p>");
</script>

</body>
</html>

方法 描述
getElementById() 返回带有指定 ID 的元素。
getElementsByTagName() 返回包含带有指定标签名称的所有元素的节点列表(集合/节点数组)。
getElementsByClassName() 返回包含带有指定类名的所有元素的节点列表。
appendChild() 把新的子节点添加到指定节点。
removeChild() 删除子节点。
replaceChild() 替换子节点。
insertBefore() 在指定的子节点前面插入新的子节点。
createAttribute() 创建属性节点。
createElement() 创建元素节点。
createTextNode() 创建文本节点。
getAttribute() 返回指定的属性值。
setAttribute() 把指定属性设置或修改为指定的值。

innerHTML 属性

innerHTML 属性可用于获取或改变任意 HTML 元素,包括 和 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html>
<body>

<p>Hello World!</p>
<p>DOM 很有用!</p>
<p>本例演示 <b>getElementsByTagName</b> 方法。</p>

<script>
x=document.getElementsByTagName("p");
document.write("第一段的文本: " + x[0].innerHTML);

document.write("第一段的文本: " + x[1].innerHTML);

document.write("第一段的文本: " + x[2].innerHTML);
</script>

</body>
</html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html>
<body>

<p>Hello World!</p>

<div id="main">
<p>DOM 很有用!</p>
<p>本例演示 <b>getElementsByTagName</b> 方法。</p>
</div>

<script>
x=document.getElementById("main").getElementsByTagName("p");
document.write("div 中的第一段的文本: " + x[0].innerHTML);
</script>

</body>
</html>

修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<html>
<body>

<p id="p1">Hello World!</p>
<p id="p2">Hello world!</p>

<script>
document.getElementById("p1").innerHTML="New text!";
</script>
<script>
document.getElementById("p2").style.color="blue";
</script>

<script>
var para=document.createElement("p");
var node=document.createTextNode("This is new.");
para.appendChild(node);

var element=document.getElementById("d1");
element.appendChild(para);
</script>

</body>
</html>

wiki blog

整理wiki blog的方法

jekyll
hexo
docsify
mdwiki
gitbook

gitbook

gitbook

npm install -g cnpm

cnpm install -g gitbook-cli

docker start gitbook

docker search -s 3 gitbook
docker pull fellah/gitbook

docker run -v /home/m/gitbook/my:/srv/gitbook -v /home/m/gitbook/my/html:/srv/html fellah/gitbook gitbook build . /srv/html

docker search -s 3 nginx
docker pull nginx

docker run –name my-nginx -v /home/m/gitbook/my/html:/usr/share/nginx/html -d -p 8080:80 nginx

So open IP:8080 to start a Web page .

How to make pdf

make pdf

p python -m SimpleHTTPServer

nohup python -m SimpleHTTPServer [port] &

SimpleHTTPServer is a module of Python.
The index.html will should be set as the homepage.

This is also a good idea to share your files.

If there isn’t an index.html page, there will shows all the files in the browser page.

:)

Docker

sudo apt-get install docker.io
sudo gpasswd -a your_user_name docker               #加入用户组
sudo service docker restart
newgrp - docker             #使用新用户组,或者也可以断开终端重连生效
docker version              #查看docker版本信息

docker下各文件默认存放在/var/lib/docker下

du -h --max-depth=1 /var/lib/docker                #查看docker目录大小

docker search licheepi               #搜索镜像
docker pull zepan/licheepi           #下载镜像
docker run zepan/licheepi apt-get install -y xxx             #在镜像中执行命令,安装某软件
docker commit -m="install something" -a="zepan"  container_id zepan/licheepi
docker login
docker push  zepan/licheepi

交互式启动

docker run -i -t learn/tutorial /bin/bash        //开启一个交互式虚拟终端
    -i    交互式
    -t     虚拟终端
    -d    后台
    -P    端口映射

docker port  id    //查看端口映射情况

docker inspect  id    //查看容器详细状态

后台启动

docker run -d learn/tutorial /bin/sh -c "while true; do echo hello world; sleep 1; done"
返回容器id:350807154a3dd17309b23bb9a9a9897dd3fc91667a7d176aca42f390808e3019


docker logs 3508 或 blissful_lamport
docker logs -f    xxxx        //类似tail -f

docker stop 3508        //通过发送信号方式停止
docker kill 3508           //kill方式停止
docker start 3508        //start -i  交互式执行
docker restart 3508


docker remove 3508
docker rm `docker ps -a -q`        //删除所有容器

主机容器互拷数据

docker cp id:/xxx/xx   /yyy/yy/
docker cp  /yyy/yy/    id:/xxx/xx

开启容器的ssh

docker run -d -p 6666:22 zepan/licheepi /usr/sbin/sshd -D

push

android@q-OptiPlex-7070:~$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: quectel
Password:
WARNING! Your password will be stored unencrypted in /home/android/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded


android@q-OptiPlex-7070:~$ docker images
REPOSITORY            TAG                 IMAGE ID       CREATED          SIZE
ubuntu                16_jdk1.8           0fc8046dc8e7   10 minutes ago   2.93GB

docker tag ubuntu:16_jdk1 quectel/imx8_android9

docker push quectel/imx8_android9

Shell

========================

case 结构

e 值 in
模式1)
    command1
    command2
    command3
;;
模式2)
    command1
    command2
    command3
;;
*)
    command1
    command2
    command3
;;
esac

例子

#!/bin/bash
var=quectel

echo $var

printf "Input a character: "
read -n 1 char
case $char in
   [a-zA-Z])
       printf "\nletter\n"
       ;;
   [0-9])
    printf "\nDigit\n"
       ;;
   [0-9])
       printf "\nDigit\n"
       ;;
   [,.?!])
       printf "\nPunctuation\n"
       ;;
 *)
    printf "\nerror\n"
esac

------------

#!/bin/bash
var=quectel

echo $(ls)

echo `pwd`


v2=hello"quectel"!

echo $v2


arr=(1 2 3)

echo ${arr[2]}
echo ${arr[@]}
echo ${#arr[*]}

autologin.vbs

Dim WshShell 
Set WshShell=WScript.CreateObject("WScript.Shell") 
WshShell.Run "cmd.exe"
WScript.Sleep 1500 
WshShell.SendKeys  "ssh m@10.66.125.234"
WshShell.SendKeys  "{ENTER}"
WScript.Sleep 1500 
WshShell.SendKeys "m"
WshShell.SendKeys "{ENTER}"

MISC

Hard to clarify…

locales

locale 是Ubuntu/Centos 用于语言环境本地化。

远程SSH 连了自己平板电脑上的WSL环境,Ubuntu环境的工作OK,但是Debian的WSL环境却出现了输入中文字符,VIM里出现无法识别的情况,出现了各种方块。
和locale有关。

之前在EC25E上移植TMUX,没成功,最后也是这个问题需要配置。

实际上Debian上支持locale,执行dpkg-reconfigure locales 也能配置,但是返回有报错,并且最终没有生效。
直接修改/etc/default/locale ,重启后也不行。

apt-get remove --purge locales -y
apt-get install locales -y

卸载重装解决问题。

后来重启后,一切恢复了,中文又再次无法

export LC_ALL=zh_CN.UTF-8

世界宁静

alais

给命令起别名

alias ls="ls --color"

UsbIp

USB over IP

How_to_setup_and_use_USB/IP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

q@q-OptiPlex-7070:~$ /usr/lib/linux-tools/5.4.0-52-generic/usbip list -l
usbip: error: failed to open /usr/share/hwdata//usb.ids
- busid 1-12 (413c:2113)
unknown vendor : unknown product (413c:2113)

- busid 1-5.4 (1976:4082)
unknown vendor : unknown product (1976:4082)

q@q-OptiPlex-7070:~$ /usr/lib/linux-tools/5.4.0-52-generic/usbip list -r 10.66.125.234
usbip: error: failed to open /usr/share/hwdata//usb.ids
Exportable USB devices
======================
- 10.66.125.234
1-4: unknown vendor : unknown product (2c7c:0125)
: /sys/devices/pci0000:00/0000:00:14.0/usb1/1-4
: unknown class / unknown subclass / unknown protocol (ef/02/01)

q@q-OptiPlex-7070:~$ sudo /usr/lib/linux-tools/5.4.0-52-generic/usbip attach -r 10.66.125.234 -b 1-4

q@q-OptiPlex-7070:~$ lsusb
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 002: ID 2c7c:0125 Quectel Wireless Solutions Co., Ltd. EC25 LTE modem
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 004: ID 1976:4082 Chipsbrand Microelectronics (HK) Co., Ltd.
Bus 001 Device 002: ID 1a40:0101 Terminus Technology Inc. Hub
Bus 001 Device 005: ID 413c:2113 Dell Computer Corp. Dell KB216 Wired Keyboard
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub


[711228.658191] vhci_hcd vhci_hcd.0: USB/IP Virtual Host Controller
[711228.658193] vhci_hcd vhci_hcd.0: new USB bus registered, assigned bus number 3
[711228.658197] vhci_hcd: created sysfs vhci_hcd.0
[711228.658219] usb usb3: New USB device found, idVendor=1d6b, idProduct=0002, bcdDevice= 5.04
[711228.658220] usb usb3: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[711228.658220] usb usb3: Product: USB/IP Virtual Host Controller
[711228.658221] usb usb3: Manufacturer: Linux 5.4.0-48-generic vhci_hcd
[711228.658222] usb usb3: SerialNumber: vhci_hcd.0
[711228.658359] hub 3-0:1.0: USB hub found
[711228.658363] hub 3-0:1.0: 8 ports detected
[711228.658459] vhci_hcd vhci_hcd.0: USB/IP Virtual Host Controller
[711228.658460] vhci_hcd vhci_hcd.0: new USB bus registered, assigned bus number 4
[711228.658477] usb usb4: We don't know the algorithms for LPM for this host, disabling LPM.
[711228.658491] usb usb4: New USB device found, idVendor=1d6b, idProduct=0003, bcdDevice= 5.04
[711228.658491] usb usb4: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[711228.658492] usb usb4: Product: USB/IP Virtual Host Controller
[711228.658493] usb usb4: Manufacturer: Linux 5.4.0-48-generic vhci_hcd
[711228.658493] usb usb4: SerialNumber: vhci_hcd.0
[711228.658595] hub 4-0:1.0: USB hub found
[711228.658599] hub 4-0:1.0: 8 ports detected
[711574.023109] usbcore: registered new device driver usbip-host
[711696.394509] vhci_hcd vhci_hcd.0: pdev(0) rhport(0) sockfd(3)
[711696.394510] vhci_hcd vhci_hcd.0: devid(65602) speed(3) speed_str(high-speed)
[711696.629478] usb 3-1: new high-speed USB device number 2 using vhci_hcd
[711696.769483] usb 3-1: SetAddress Request (2) to port 0
[711696.837940] usb 3-1: New USB device found, idVendor=2c7c, idProduct=0125, bcdDevice= 3.18
[711696.837947] usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[711696.837950] usb 3-1: Product: Android
[711696.837953] usb 3-1: Manufacturer: Android
[711696.962058] usbcore: registered new interface driver usbserial_generic
[711696.962063] usbserial: USB Serial support registered for generic
[711697.126640] usbcore: registered new interface driver option
[711697.126647] usbserial: USB Serial support registered for GSM modem (1-port)
[711697.126694] option 3-1:1.0: GSM modem (1-port) converter detected
[711697.126788] usb 3-1: GSM modem (1-port) converter now attached to ttyUSB0
[711697.126810] option 3-1:1.1: GSM modem (1-port) converter detected
[711697.126869] usb 3-1: GSM modem (1-port) converter now attached to ttyUSB1
[711697.126889] option 3-1:1.2: GSM modem (1-port) converter detected
[711697.126917] usb 3-1: GSM modem (1-port) converter now attached to ttyUSB2
[711697.126935] option 3-1:1.3: GSM modem (1-port) converter detected
[711697.126961] usb 3-1: GSM modem (1-port) converter now attached to ttyUSB3
[711697.126990] option 3-1:1.5: GSM modem (1-port) converter detected
[711697.127014] option 3-1:1.6: GSM modem (1-port) converter detected
[711697.127035] option 3-1:1.7: GSM modem (1-port) converter detected
[711697.135638] usbcore: registered new interface driver cdc_wdm
[711697.169606] qmi_wwan 3-1:1.4: cdc-wdm1: USB WDM device
[711697.174201] qmi_wwan 3-1:1.4 wwan0: register 'qmi_wwan' at usb-vhci_hcd.0-1, WWAN/QMI device, 2e:07:fd:3d:7e:a5
[711697.174241] usbcore: registered new interface driver qmi_wwan
[711697.351729] mc: Linux media interface: v0.10
[711697.413620] usbcore: registered new interface driver snd-usb-audio
[711699.152259] vhci_hcd: unlink->seqnum 51
[711699.152260] vhci_hcd: urb->status -104
[711699.264750] vhci_hcd: unlink->seqnum 62
[711699.264752] vhci_hcd: urb->status -104


进程绑定CPU

linux下把进程/线程绑定到特定cpu核上运行

CPU Core

cat /proc/cpuinfo | grep "physical id" | sort | uniq | wc -l

查看进程绑定在哪个CPU

taskset -cp 进程PID

绑定进程到CPU

taskset -cp cpu核序号 进程PID

swap 分区

swap 在windows PC上也有这个功能,就是把硬盘的一部分空间当作内存使用,用来应付内存不足的情况。

该区域也不宜设置过大,否则OS就不会节约使用内存。

/etc/fstab

磁盘被手动挂载之后都必须把挂载信息写入/etc/fstab这个文件中,否则下次开机启动时仍然需要重新挂载。
系统开机时会主动读取/etc/fstab这个文件中的内容,根据文件里面的配置挂载磁盘。

https://blog.csdn.net/kepa520/article/details/81315430

strace

原理是跟踪进程和信号的系统调用

strace cat /dev/null

execve("/usr/bin/cat", ["cat", "/dev/null"], 0x7ffe960fe6b8 /* 26 vars */) = 0
brk(NULL)                               = 0x55f11ab99000
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffebb813ff0) = -1 EINVAL (无效的参数)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (没有那个文件或目录)
...


strace -tt -T -v -f -e trace=file -o /data/log/strace.log -s 1024 -p 23489
  • -tt 在每行输出的前面,显示毫秒级别的时间
  • -T 显示每次系统调用所花费的时间
  • -v 对于某些相关调用,把完整的环境变量,文件stat结构等打出来。
  • -f 跟踪目标进程,以及目标进程创建的所有子进程
  • -e 控制要跟踪的事件和跟踪行为,比如指定要跟踪的系统调用名称
  • -o 把strace的输出单独写到指定的文件
  • -s 当系统调用的某个参数是字符串时,最多输出指定长度的内容,默认是32个字节
  • -p 指定要跟踪的进程pid, 要同时跟踪多个pid, 重复多次-p选项即可。

跟踪nginx, 看其启动时都访问了哪些文件

strace -tt -T -f -e trace=file -o /data/log/strace.log -s 1024 ./nginx

strace命令用法

strace也不是真正的万能。当目标进程卡死在用户态时,strace就没有输出了。

这个时候我们需要其他的跟踪手段,比如gdb/perf/SystemTap等。

备注:

1、perf原因kernel支持

2、ftrace  kernel支持可编程

3、systemtap 功能强大,RedHat系统支持,对用户态,内核态逻辑都能探查,使用范围更广

dmesg 的ring buffer

dmesg -s 指定唤醒缓冲器大小

ps top 查看进程运行在哪个cpu上

ps -eo pid,args,psr

psr 

ps -o pid,psr,comm -p <pid>

判断Linux进程在哪个CPU核运行的方法

ping

TTL

当我们在使用 ping 命令时,返回结果里会带一个 TTL 值。这个东西的含义其实就是Time To Live,指的是报文在网络中能够存活的限制。以前这个限制方式是设定一个时间(Time To Live中的Time就是这样来的),当报文在网络中转发时,时间超过这个限制,最后一个收到报文的路由点就会把它扔掉,而不继续转发。后来把时间限制改为了跳数限制,就是当报文在网络中转发时,每经过一个路由点,就把预先设定的这个TTL数值减 1,直到最后 TTL=1 时报文就被扔掉,不向下转发。

路由点:我这里是指完成路由功能的机器,因为并不是只有路由器才可以完成路由转发功能,比如主机可以配置路由转发。

所以,回包中的 TTL 表示目标主机返回的报文到达本机后,从它预设的 TTL 值减小到现在的值。

临时开启 ping。

echo 0 > /proc/sys/net/ipv4/icmp_echo_ignore_all

临时禁用 ping。

echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all 

epoll和/proc

当创建好epoll句柄后,它就是会占用一个fd值,在linux下如果查看/proc/进程id/fd/,是能够看到这个fd的,所以在使用完epoll后,必须调用close()关闭,否则可能导致fd被耗尽。

epoll创建的fd是:

lrwx------ 1 root root 64 Aug 20 11:04 3 -> anon_inode:[eventpoll]

这种类型的inode,是epoll创建的。

lrwx------ 1 root root 64 Aug 20 11:04 4 -> socket:[1126425]

在相应进程的/proc/$pid/fd 目录下存放了此进程所有打开的fd
lrwx------ 1 root root 64 Nov 21 09:44 133 -> /dev/sda1
lrwx------ 1 root root 64 Nov 21 09:44 134 -> /dev/sdb1
lrwx------ 1 root root 64 Nov 21 09:44 136 -> /dev/sdb1
lrwx------ 1 root root 64 Nov 21 09:44 137 -> socket:[22460]
lrwx------ 1 root root 64 Nov 21 09:44 138 -> socket:[7326842]
lrwx------ 1 root root 64 Nov 21 09:44 139 -> socket:[7341066]

socket:后面的一串数字是什么呢?

其实是该socket的inode号

设备树

alias 别名

dts学习

vfork

vfork 创建的子进程执行的时候,父进程睡眠,子进程退出后,父进程才继续执行。并且父子进程使用的资源是同一块。

git 同时传到两个仓库

git remote set-url –add origin git@github.com.git

使用qemu搭建arm嵌入式linux开发环境

在arm开发板上成功运行Linux系统,我们有如下三个方面的任务:

制作bootloader;
编译linux内核、linux内核模块、linux设备树;
制作根文件系统。

我们使用qemu虚拟机来上手嵌入式linux的开发。

###安装qemu与arm交叉编译工具

###Linux内核与设备树编译

下载Linux内核:https://www.kernel.org/

git clone https://mirrors.tuna.tsinghua.edu.cn/git/linux.git

https://mirror.bjtu.edu.cn/kernel/linux/kernel/

make vexpress_defconfig

make zImage

make modules

make dtbs

得到zImage、dtb

尝试启动

1
2
qemu-system-arm -M vexpress-a9 -m 512M -kernel arch/arm/boot/zImage -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic -append "console=ttyAMA0"

看到

log
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

rtc-pl031 10017000.rtc: setting system clock to 2020-11-02 09:39:39 UTC (1604309979)
ALSA device list:
#0: ARM AC'97 Interface PL041 rev0 at 0x10004000, irq 33
input: ImExPS/2 Generic Explorer Mouse as /devices/platform/smb/smb:motherboard/smb:motherboard:iofpga@7,00000000/10007000.kmi/serio1/input/input2
VFS: Cannot open root device "(null)" or unknown-block(0,0): error -6
Please append a correct "root=" boot option; here are the available partitions:
1f00 131072 mtdblock0 (driver?)
1f01 32768 mtdblock1 (driver?)
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.4.99 #1
Hardware name: ARM-Versatile Express
[<80016454>] (unwind_backtrace) from [<80012ee0>] (show_stack+0x10/0x14)
[<80012ee0>] (show_stack) from [<80243aac>] (dump_stack+0x94/0xa8)
[<80243aac>] (dump_stack) from [<800a5638>] (panic+0x9c/0x200)
[<800a5638>] (panic) from [<8062f250>] (mount_block_root+0x1c0/0x25c)
[<8062f250>] (mount_block_root) from [<8062f408>] (mount_root+0x11c/0x124)
[<8062f408>] (mount_root) from [<8062f568>] (prepare_namespace+0x158/0x1a0)
[<8062f568>] (prepare_namespace) from [<8062eeec>] (kernel_init_freeable+0x268/0x278)
[<8062eeec>] (kernel_init_freeable) from [<804a440c>] (kernel_init+0x8/0xe8)
[<804a440c>] (kernel_init) from [<8000f4f8>] (ret_from_fork+0x14/0x3c)
---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

###busybox

https://busybox.net/downloads/

编译生成一个 __install 文件夹

###制作根文件系统

mkdir rootfs

将_install 目录里的内容拷贝到rootfs目录中

新建目录 mkdir lib

将arm交叉编译器的库复制过来:cp -r /usr/arm-linux-gnueabi/lib/* lib/

在rootfs目录下新建目录mkdir dev/,进入该目录cd dev/,创建节点sudo mknod -m 666 tty1 c 4 1(串口字符设备,主设备号为4,从设备号为1)

重复创建多个串口设备,注意分配好从设备号:

创建一个控制台节点:mknod -m 666 console c 5 1

创建一个空节点:mknod -m 666 null c 1 3

回到home目录,输入命令dd if=/dev/zero of=rootfs.ext3 bs=1M count=32生成虚拟SD卡系统镜像,可以得到一个rootfs.ext3文件。
格式化该镜像:mkfs.ext3 rootfs.ext3
挂载该镜像到本地:mount -t ext3 rootfs.ext3 /mnt -o loop

将之前准备的rootfs目录下的所有文件都拷贝到该镜像挂载点:cp -r /home/zvcv/rootfs/* /mnt/

卸载:umount /mnt/
进入linux源码目录: cd linux/

使用qemu启动内核:qemu-system-arm -M vexpress-a9 -m 512M -kernel arch/arm/boot/zImage -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic -append “root=/dev/mmcblk0 rw console=ttyAMA0” -sd /home/zvcv/rootfs.ext3,这里比之前多指定了一个sd镜像。

点击回车,进入命令行,linux启动完毕。

我遇到了无法启动,原因是内核编译选项选的是ext4 ,所以格式化的时候选mkfs.ext4

###uboot

https://ftp.denx.de/pub/u-boot/

不要用最新版本

scripts/kconfig/conf –syncconfig Kconfig
UPD include/config.h
GEN include/autoconf.mk.dep
CFG u-boot.cfg
GEN include/autoconf.mk
UPD include/generated/dt.h
UPD include/generated/timestamp_autogenerated.h
UPD include/config/uboot.release
*** Your GCC is older than 6.0 and is not supported
arch/arm/config.mk:66: recipe for target ‘checkgcc6’ failed
make: *** [checkgcc6] Error 1

我的arm-linux-gnuebi-gcc 是5.5

换2015年的uboot才能build pass

###NFS

sudo apt-get install uml-utilities bridge-utils

cd linux-4.4.232/

make LOADADDR=0x60003000 uImage -j4

mkimage command not found U-Boot images will not be built —>

sudo apt-get install u-boot-tools

sudo apt-get install tftp-hpa tftpd-hpa xinetd

u-boot 要能加载uImage,需要修改

默认的bootcmd,变成tftp加载tftp server上的uImage

vim include/configs/vexpress_common.h

注释默认的 CONFIG_BOOTCOMMAND

添加

#define CONFIG_BOOTCOMMAND “tftp 0x60003000 uImage; setenv bootargs’root=/dev/mmcblk0 console=ttyAMA0’; bootm 0x60003000”

另外一个说法是

#define CONFIG_BOOTCOMMAND “tftp 0x60003000 uImage; tftp 0x60500000 vexpress-v2p-ca9.dtb; setenv bootargs ‘root=/dev/mmcblk0 console=ttyAMA0’; bootm 0x60003000 - 0x60500000”

可以配置IP和netmask

1
2
3
#define CONFIG_IPADDR   192.168.1.49
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_SERVERIP 192.168.1.88

在Quectel的台式机虚拟机里的桥接网卡,实际配置成

1
2
3
#define CONFIG_IPADDR   192.168.1.49
#define CONFIG_NETMASK 255.255.254.0
#define CONFIG_SERVERIP 10.66.83.84

How to Create a Deamon Service

信号

From

https://linoxide.com/linux-how-to/linux-signals-part-1

https://linoxide.com/linux-how-to/linux-kill-command-examples/

Signals in Linux is a very important concept to understand. This is because signals are used in some of the common activities that you do through Linux command line. For example, whenever you press Ctrl+c to terminate an executing command from command line, you use signals.

Whenever you use ‘kill -9 [pid]’ to kill a process, you use signals. So, it is very useful to know at least the basics of signals and that is exactly what we will discuss in this tutorial.

A signal is nothing but a way of communicating a message from one process to another. These messages are popularly known as notifications which the receiving process is free to process, ignore or leave it up to the OS to take default action (more on these options later). A notification sent by the sender process to the receiving process can be of various types. For example, a notification can be to kill the receiving process or let it know that it has accessed an invalid memory area or it can be a notification of the availability of a resource (that was busy earlier) etc. So, you can see that signals are nothing but just another way of IPC (inter Process Communication).

Signals are important, in-fact very important because they drive some of the most popular programming and system administration activities.

For example, let’s take the example of a debugger. Most of the programmers use a debugger to debug their program code while it is executing. If you would have ever used a debugger, you would know that breakpoints are used to halt the execution of a program at specified lines of code.

What makes a program aware that a breakpoint has been hit and it needs to halt the execution?

Yes, it is a signal (SIGSTOP) that is sent to the program in this case. And when the user is done with debugging, a signal (SIGCONT) is sent to the program – after which the program continues the execution.

###Different Types Of Signals

root@m:/# kill -l

 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
 6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR1
11) SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR
31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

###Difference between SIGTERM, SIGKILL, SIGINT, SIGQUIT

SIGQUIT

On POSIX-compliant platforms, SIGQUIT is the signal sent to a process by its controlling terminal when the user requests that the process perform a core dump. SIGQUIT can usually be induced with Control-. On Linux, one may also use Ctrl-4 or, on the virtual console, the SysRq key.

SIGTERM
SIGTERM is the default signal sent to a process by the kill or killall commands. It causes the termination of a process, but unlike the SIGKILL signal, it can be caught and interpreted (or ignored) by the process. Therefore, SIGTERM is akin to asking a process to terminate nicely, allowing cleanup and closure of files. For this reason, on many Unix systems during shutdown, init issues SIGTERM to all processes that are not essential to powering off, waits a few seconds, and then issues SIGKILL to forcibly terminate any such processes that remain.

SIGINT

On POSIX-compliant platforms, SIGINT is the signal sent to a process by its controlling terminal when a user wishes to interrupt the process. SIGINT is sent when the user on the process’ controlling terminal presses the interrupt the running process key typically Control-C, but on some systems, the “delete” character or “break” key.

SIGKILL

On POSIX-compliant platforms, SIGKILL is the signal sent to a process to cause it to terminate immediately. When sent to a program, SIGKILL causes it to terminate immediately. In contrast to SIGTERM and SIGINT, this signal cannot be caught or ignored, and the receiving process cannot perform any clean-up upon receiving this signal.

How a Program Handles Signals?
A program can handle signals in the following three ways:

A program may provide its own signal handler for handling a particular signal - This is especially important in those cases where a program has to perform some tasks (for example - memory clean-up activities) in response to the received signal. A signal handler is nothing but a function defined in the program code that gets executed automatically (actually it gets triggered by the OS kernel) when a signal is received by the program.
A Program may do nothing on receipt of a signal - Every signal has a default action associated with it. In a scenario where a program just doesn’t care for a signal, the default action corresponding to that particular signal is taken by the OS kernel.
A program may choose to ignore a signal - In this situation, the signal (or set of signals) are blocked and are hence not delivered to the program. A program may choose to ignore signals which – the programmer thinks – are irrelevant to it.

###Examples

http://www.yolinux.com/TUTORIALS/C++Signals.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

// Define the function to be called when ctrl-c (SIGINT) signal is sent to process

void signal_callback_handler(int signum)
{
printf("Caught signal %d\n",signum);
// Cleanup and close up stuff here
// Terminate program
exit(signum);
}

int main()
{
// Register signal and signal handler
signal(SIGINT, signal_callback_handler);
while(1)
{
printf("Program processing stuff here.\n");
sleep(1);
}
return EXIT_SUCCESS;
}

Wifi adb

./adb connect 192.168.1.180:5555

setprop service.adb.tcp.port 5555

stop adbd
start adbd

pstree

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
pstree: unrecognized option '--help'
用法:pstree [-acglpsStTuZ] [ -h | -H 进程号 ] [ -n | -N 类型 ]
[ -A | -G | -U ] [ 进程号 | 用户 ]
或:pstree -V

显示进程树。

-a, --arguments 显示命令行参数
-A, --ascii 使用 ASCII 行绘制字符
-c, --compact-not 不要对完全相同的子树进行压缩
-C, --color=类型 按照指定属性对进程上色
(age)
-g, --show-pgids 显示进程组 ID;隐含启用 -c 选项
-G, --vt100 使用 VT100 行绘制字符
-h, --highlight-all 高亮显示当前进程和其所有祖先
-H PID, --highlight-pid=PID
高亮显示指定 PID 对应的进程和其所有祖先
-l, --long 不要截断长行
-n, --numeric-sort 按照 PID 对输出进行排序
-N 类型, --ns-sort=类型
按照指定命名空间类型对输出进行排序
(cgroup, ipc, mnt, net, pid, user, uts)
-p, --show-pids 显示 PID;隐含启用 -c 选项
-s, --show-parents 显示所选进程的父进程
-S, --ns-changes 显示命名空间的变化
-t, --thread-names 显示完整线程名称
-T, --hide-threads 隐藏线程,只显示进程
-u, --uid-changes 显示用户 ID(UID)的变化
-U, --unicode 使用 UTF-8(Unicode)的行绘制字符
-V, --version 显示版本信息
-Z, --security-context
显示 SELinux 安全上下文

进程号 从指定进程号开始;默认为 1(init)
用户 仅显示从指定用户的进程开始的进程树

pidof

root@m:/usr/src/linux-headers-5.4.0-26-generic/include# ps -a
PID TTY TIME CMD
2097 pts/0 00:00:00 sudo
2948 pts/1 00:00:00 bash
2969 pts/0 00:00:00 tmux: client
45805 pts/9 00:00:00 ps
root@m:/usr/src/linux-headers-5.4.0-26-generic/include# pidof tmux
2971 2969

chroot

命令用于改变根目录

xargs

xargs 是一个强有力的命令,它能够捕获一个命令的输出,然后传递给另外一个命令。

somecommand |xargs -item command

-a file 从文件中读入作为sdtin
-e flag ,注意有的时候可能会是-E,flag必须是一个以空格分隔的标志,当xargs分析到含有flag这个标志的时候就停止。
-p 当每次执行一个argument的时候询问一次用户。
-n num 后面加次数,表示命令在执行的时候一次用的argument的个数,默认是用所有的。
-t 表示先打印命令,然后再执行。
-i 或者是-I,这得看linux支持了,将xargs的每项名称,一般是一行一行赋值给 {},可以用 {} 代替。
-r no-run-if-empty 当xargs的输入为空的时候则停止xargs,不用再去执行了。
-s num 命令行的最大字符数,指的是 xargs 后面那个命令的最大命令行字符数。
-L num 从标准输入一次读取 num 行送给 command 命令。
-l 同 -L。
-d delim 分隔符,默认的xargs分隔符是回车,argument的分隔符是空格,这里修改的是xargs的分隔符。
-x exit的意思,主要是配合-s使用。。
-P 修改最大的进程数,默认是1,为0时候为as many as it can ,这个例子我没有想到,应该平时都用不到的吧。

VIM r

:r
可以把其他文本文件内容插入到当前文件中

列出ubuntu上所有的服务

systemctl list-units –all –type=service

将当前文件中除了src目录全部移动到src目录

mv `ls | grep -v src | xargs` src

xargs 将ls 的结果作为一行

grep -v 反向

mv `(ls | grep -v 'example[12]' | xargs)` example1

将除了 example1和example2剩下的所有文件全部移动到example1中去

nohup

不挂断地运行命令

nohup cmd &

当前shell关闭后,会将该进程的父进程指向init(PID 1)

TC

show / manipulate traffic control settings

Usage:  tc [ OPTIONS ] OBJECT { COMMAND | help }
        tc [-force] -batch filename
where  OBJECT := { qdisc | class | filter | chain |
                    action | monitor | exec }
       OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[aw] |
                    -o[neline] | -j[son] | -p[retty] | -c[olor]
                    -b[atch] [filename] | -n[etns] name | -N[umeric] |
                     -nm | -nam[es] | { -cf | -conf } path }

详细参考 man tc

将 eth0 网卡的传输设置为延迟100毫秒发送。

$ tc  qdisc  add  dev  eth0  root  netem  delay  100ms  

延迟值不会这么精确,会有一定的波动,下面命令模拟带有波动性的延迟值:

$ tc  qdisc  add  dev  eth0  root  netem  delay  100ms  10ms

root@m:/home/m/Smart210# tc  qdisc
qdisc noqueue 0: dev lo root refcnt 2
qdisc fq_codel 0: dev eth0 root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 32Mb ecn
qdisc netem 8001: dev wlan0 root refcnt 2 limit 1000 delay 100.0ms
qdisc noqueue 0: dev docker0 root refcnt 2

模拟网络丢包

将 eth0 网卡的传输设置为随机丢掉 1% 的数据包。

 $ tc  qdisc  add  dev  eth0  root  netem  loss  1%  

linux下的tc工具使用

模拟数据包损坏\模拟数据包乱序\

设置延时

$ sudo tc qdisc add dev eth0 root netem delay 4s

取消延时

$ sudo tc qdisc del dev eth0 root netem delay 4s

配合iptables 使用

根据commit id生成patch

git format-patch -1 d9a64c74ff0244b96a44fa27abcdc411d29f487

vim 批量tab

shift+V 选中

shift+>

openwrt安装ipk

ssh连接路由命令安装
或者用ssh软件PuTTY连接路由器

opkg update
opkg install 软件包网址

或者用winscp连接路由 然后上传包到/tmp/下

opkg update
opkg install /tmp/xxx.ipk

du和df

q@q-K501LB:~/Khadas$ du -d 1 -h Android_P/
6.5G    Android_P/external
350M    Android_P/toolchain
1.6G    Android_P/tools
22G     Android_P/prebuilts
144G    Android_P/.repo
84M     Android_P/libcore
912K    Android_P/pdk
329M    Android_P/bootloader
31M     Android_P/sdk
811M    Android_P/common
3.3M    Android_P/compatibility
5.8M    Android_P/platform_testing
124M    Android_P/test
14M     Android_P/build
22M     Android_P/bootable
34M     Android_P/bionic
436M    Android_P/developers
876K    Android_P/kernel
1.7G    Android_P/vendor
1.7G    Android_P/frameworks
404K    Android_P/libnativehelper
131M    Android_P/development
167M    Android_P/device
90M     Android_P/art
553M    Android_P/hardware
691M    Android_P/packages
470M    Android_P/system
779M    Android_P/cts
80G     Android_P/out
27M     Android_P/dalvik
261G    Android_P/

-h 结尾以B K M G为单位,方便阅读。df 命令也一样,也有-h选项

bash dash

for i in {1..7}
do
        echo $i
done

用bash 执行可以,但是dash 不行

git 删除分支

现在在zh分支上,想删除zh分支

  1 先切换到别的分支: git checkout master

  2 删除本地分支: git branch -d zh

  3 如果删除不了可以强制删除,git branch -D zh

  4 有必要的情况下,删除远程分支(慎用):git push origin --delete zh

git 如何merge 分支

xxx

expect 的用法

当出现 username 的时候,自动输入 QuectelWB.

自动ssh登录输入密码

Shell 脚本如下

#!/usr/bin/expect

spawn ssh m@10.66.125.234
expect "*password:"
send "m\r"
expect "*$"
interact

find 的用法

查找/etc下的链接属性的文件,大小小于1kb的

find /etc -type l -o -size -1k

chgrp

修改文件所属组群chgrp

修改文件所属组群很简单-chgrp命令,就是change group的缩写(我们可以利用这些来记忆命令)

语法:

chgrp  组群  文件名/目录 

相比于chwon 更不常用

nslookup

android@q-OptiPlex-7070:~/IMX8_Android9$ nslookup www.baidu.com 8.8.8.8
Server:         8.8.8.8
Address:        8.8.8.8#53

Non-authoritative answer:
www.baidu.com   canonical name = www.a.shifen.com.
Name:   www.a.shifen.com
Address: 14.215.177.39
Name:   www.a.shifen.com
Address: 14.215.177.38

:)

孤儿进程和僵尸进程

TASK_UNINTERRUPTIBLE 的进程 在ps 的时候能看到标注为 D ,而TASK_INTERRUPTIBLE的进程处于 S状态。
D 状态的程序,譬如 vfork创建子进程后,父进程就是D状态。
D状态的进程,只能 重启操作系统或者等其资源满足后才能关闭。无法用信号操作kill掉。

正常情况,子进程退出,会有SIGCHLD信号通知父进程。一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。

孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。

pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);

status

WIFEXITED(status)
returns true if the child terminated normally, that is, by calling exit(3) or _exit(2), or by returning from main().
WEXITSTATUS(status)
returns the exit status of the child. This consists of the least significant 8 bits of the status argument that the child specified in a call to exit(3) or _exit(2) or as the argument for a return statement in main(). This macro should only be employed if WIFEXITED returned true.
WIFSIGNALED(status)
returns true if the child process was terminated by a signal.
WTERMSIG(status)
returns the number of the signal that caused the child process to terminate. This macro should only be employed if WIFSIGNALED returned true.
WCOREDUMP(status)
returns true if the child produced a core dump. This macro should only be employed if WIFSIGNALED returned true. This macro is not specified in POSIX.1-2001 and is not available on some UNIX implementations (e.g., AIX, SunOS). Only use this enclosed in #ifdef WCOREDUMP ... #endif.
WIFSTOPPED(status)
returns true if the child process was stopped by delivery of a signal; this is only possible if the call was done using WUNTRACED or when the child is being traced (see ptrace(2)).
WSTOPSIG(status)
returns the number of the signal which caused the child to stop. This macro should only be employed if WIFSTOPPED returned true.
WIFCONTINUED(status)
(since Linux 2.6.10) returns true if the child process was resumed by delivery of SIGCONT.

WSL 服务自动启动的正确方法

wsl 支持后台运行

在WSL中创建 /etc/init.wsl

#! /bin/sh
/etc/init.d/cron $1
/etc/init.d/ssh $1
/etc/init.d/supervisor $1

WIN+R

shell:startup
创建Windows系统的启动脚本 debian.vbs

Set ws = CreateObject("Wscript.Shell")
ws.run "wsl -d debian -u root /etc/init.wsl start", vbhide

WindowsTerminal

支持多选项卡、窗格、Unicode、UTF-8和自定义标题、主题、自动补全,支持WSL、PowerShell。

www.github.com/microsoft/terminal

https://docs.microsoft.com/zh-cn/windows/terminal/

###默认快捷键

快捷键 功能
Shift + Alt + + 横向分屏
Shift + Alt + - 竖向分屏
Ctrl + Shift + w 取消分屏/关闭当前标签页
Alt + 方向键 分屏间移动光标
Alt + Shift + 方向键 调整当前分屏区大小

###settings.json

// 全局设置
{
    "$schema": "https://aka.ms/terminal-profiles-schema",

    "defaultProfile": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}", // 默认配置文件

    "disabledProfileSources": "[]", // 禁用动态配置文件

    "theme": "system", // 深色/浅色主题

    "alwaysShowTabs": true, // 始终显示选项卡

    "tabWidthMode": "equal", // 选项卡宽度模式

    "confirmCloseAllTabs": true, // 隐藏关闭所有选项卡弹出窗口

    "startOnUserLogin": false, // 在计算机启动时启动

    "launchMode": "default", // 启动大小(窗口)

    "initialPosition": ",", // 启动位置(窗口)

    "initialCols": 120, // 首次启动时的列

    "initialRows": 30, // 首次启动时的行

    "showTabsInTitlebar": true, // 显示/隐藏标题栏

    "showTerminalTitleInTitlebar": true, // 设置标题栏中的文本

    "copyOnSelect": true, // 选择内容后复制

    "copyFormatting": true, // 复制格式

    //"wordDelimiters": "/\()"'-:,.;<>~!@#$%^&*|+=[]{}~?", // 字分隔符

    "rowsToScroll": "system", // 滚动速度

    "snapToGridOnResize": true, // 窗口大小调整行为

    "experimental.rendering.forceFullRepaint": true, // 屏幕重绘

    "experimental.rendering.software": true, // 软件渲染

    // 配置文件
    "profiles":
    {
        // 适用所有配置文件的设置
    "defaults":
    {
            "startingDirectory": "%USERPROFILE%", // 起始目录

            "icon": "D:\\QuectelLogo.png", // 图标

            "tabTitle": "BiaoNeverSurrender", // 自定义选项卡标题

            "suppressApplicationTitle": true, // 禁止shell更改标题

            "fontFace": "Fira Code Retina", // 字体

            "fontSize": 12, // 字体大小

            "fontWeight": "normal", // 字体粗细

            "padding": "8, 8, 8, 8", // 填充(内容距离界面的内部距离)

            "antialiasingMode": "cleartype", // 消除文本锯齿

            "cursorShape": "bar", // 光标形状

            "cursorColor": "#E6FF00", // 光标颜色

            //"cursorHeight": 25, // 光标高度("cursorShape"设置为"vintage"时可用)

            "altGrAliasing": true, // AltGr别名

            "colorScheme": "Ubuntu", // 配色方案

            //"selectionBackground": "#0000e6", // 所选内容的背景色(选用"colorScheme"内的)

            "useAcrylic": true, // 启用 acrylic(毛玻璃特效)

            "acrylicOpacity": 0.9, // Acrylic 不透明度

            "backgroundImage": "C:\\Users\\DustinWinFiles\\Pictures\\colorful.jpg", // 背景图像设置

            "backgroundImageStretchMode": "uniformToFill", // 背景图像拉伸模式

            "backgroundImageAlignment": "center", // 背景图像对齐

            "backgroundImageOpacity": 0.5, // 背景图像不透明度

            "scrollbarState": "visible", // 滚动条可见性

            "snapOnInput": true, // 键入时滚动到输入行

            "historySize": 9001, // 历史记录大小

            "closeOnExit": "graceful", // 退出时配置文件的关闭方式(输入exit退出命令窗口)

            //"experimental.retroTerminalEffect": false // 怀旧式终端效果

            "alwaysOnTop": true // 始终处于顶部模式
    },

        // 配置文件列表
    "list":
    [
        {
        "guid": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}", // PowerShell唯一标识符

        "name": "Windows PowerShell", // 名称

        "commandline": "powershell.exe", // 命令行

        "hidden": false // 隐藏下拉列表中的某个配置文件
        },
        {
        "guid": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}", // CMD唯一标识符

        "name": "命令提示符", // 名称

        "commandline": "cmd.exe", // 命令行

        "hidden": false // 隐藏下拉列表中的某个配置文件
        },
        {
        "guid": "{b453ae62-4e3d-5e58-b989-0a998ec441b8}", // Azure Cloud Shell唯一标识符

        "hidden": true, // 隐藏下拉列表中的某个配置文件

        "name": "Azure Cloud Shell", // 名称

        "source": "Windows.Terminal.Azure" // 源
        },
        {
        "guid": "{07b52e3e-de2c-5db4-bd2d-ba144ed6c273}",
        "hidden": false,
        "name": "Ubuntu-20.04",
        "source": "Windows.Terminal.Wsl"
        },
        {
        "guid": "{6f9994f0-4403-5e85-9cce-98e5da3839bb}",
        "hidden": false,
        "name": "Ubuntu-16.04",
        "source": "Windows.Terminal.Wsl"
        }
    ]
    },

    // 主题(配色方案)
    "schemes": [
        {
          "name": "Ubuntu",

          "black": "#2e3436",

          "red": "#cc0000",

          "green": "#4e9a06",

          "yellow": "#c4a000",

          "blue": "#3465a4",

          "purple": "#75507b",

          "cyan": "#06989a",

          "white": "#d3d7cf",

          "brightBlack": "#555753",

          "brightRed": "#ef2929",

          "brightGreen": "#8ae234",

          "brightYellow": "#fce94f",

          "brightBlue": "#729fcf",

          "brightPurple": "#ad7fa8",

          "brightCyan": "#34e2e2",

          "brightWhite": "#eeeeec",

          "background": "#300a24", // 背景色

          "foreground": "#eeeeec" // 前景色
        }
    ],

    // 按键绑定
    "keybindings":
    [
        { "command": "closeWindow", "keys": "alt+f4" }, // 关闭窗口

        { "command": "find", "keys": "ctrl+shift+f" }, // 查找

        { "command": "openSettings", "keys": "ctrl+," }, // 打开设置文件

        { "command": { "action": "openSettings", "target": "defaultsFile" }, "keys": "ctrl+alt+," }, // 打开设置文件

        { "command": "toggleFullscreen", "keys": "alt+enter" }, // 切换全屏

        { "command": "toggleFullscreen", "keys": "f11" }, // 切换全屏

        { "command": "closeTab", "keys": "ctrl+alt+f4" }, // 关闭选项卡

        { "command": "duplicateTab", "keys": "ctrl+shift+d" }, // 复制选项卡

        { "command": "newTab", "keys": "ctrl+shift+t" }, // 新建选项卡

        { "command": { "action": "newTab", "index": 0 }, "keys": "ctrl+shift+1" }, // 新建选项卡

        { "command": { "action": "newTab", "index": 1 }, "keys": "ctrl+shift+2" }, // 新建选项卡

        { "command": { "action": "newTab", "index": 2 }, "keys": "ctrl+shift+3" }, // 新建选项卡

        { "command": { "action": "newTab", "index": 3 }, "keys": "ctrl+shift+4" }, // 新建选项卡

        { "command": { "action": "newTab", "index": 4 }, "keys": "ctrl+shift+5" }, // 新建选项卡

        { "command": { "action": "newTab", "index": 5 }, "keys": "ctrl+shift+6" }, // 新建选项卡

        { "command": { "action": "newTab", "index": 6 }, "keys": "ctrl+shift+7" }, // 新建选项卡

        { "command": { "action": "newTab", "index": 7 }, "keys": "ctrl+shift+8" }, // 新建选项卡

        { "command": { "action": "newTab", "index": 8 }, "keys": "ctrl+shift+9" }, // 新建选项卡

        { "command": "nextTab", "keys": "ctrl+tab" }, // 打开下一个选项卡

        { "command": "prevTab", "keys": "ctrl+shift+tab" }, // 打开上一个选项卡

        { "command": { "action": "switchToTab", "index": 0 }, "keys": "ctrl+alt+1" }, // 打开特定的选项卡

        { "command": { "action": "switchToTab", "index": 1 }, "keys": "ctrl+alt+2" }, // 打开特定的选项卡

        { "command": { "action": "switchToTab", "index": 2 }, "keys": "ctrl+alt+3" }, // 打开特定的选项卡

        { "command": { "action": "switchToTab", "index": 3 }, "keys": "ctrl+alt+4" }, // 打开特定的选项卡

        { "command": { "action": "switchToTab", "index": 4 }, "keys": "ctrl+alt+5" }, // 打开特定的选项卡

        { "command": { "action": "switchToTab", "index": 5 }, "keys": "ctrl+alt+6" }, // 打开特定的选项卡

        { "command": { "action": "switchToTab", "index": 6 }, "keys": "ctrl+alt+7" }, // 打开特定的选项卡

        { "command": { "action": "switchToTab", "index": 7 }, "keys": "ctrl+alt+8" }, // 打开特定的选项卡

        { "command": { "action": "switchToTab", "index": 8 }, "keys": "ctrl+alt+9" }, // 打开特定的选项卡

        { "command": "closePane", "keys": "ctrl+shift+w" }, // 关闭窗格

        { "command": { "action": "moveFocus", "direction": "down" }, "keys": "alt+down" }, // 移动窗格焦点

        { "command": { "action": "moveFocus", "direction": "left" }, "keys": "alt+left" }, // 移动窗格焦点

        { "command": { "action": "moveFocus", "direction": "right" }, "keys": "alt+right" }, // 移动窗格焦点

        { "command": { "action": "moveFocus", "direction": "up" }, "keys": "alt+up" }, // 移动窗格焦点

        { "command": { "action": "resizePane", "direction": "down" }, "keys": "alt+shift+down" }, // 调整窗格大小

        { "command": { "action": "resizePane", "direction": "left" }, "keys": "alt+shift+left" }, // 调整窗格大小

        { "command": { "action": "resizePane", "direction": "right" }, "keys": "alt+shift+right" }, // 调整窗格大小

        { "command": { "action": "resizePane", "direction": "up" }, "keys": "alt+shift+up" }, // 调整窗格大小

        { "command": { "action": "splitPane", "split": "auto", "splitMode": "duplicate" }, "keys": "alt+shift+d" }, // 拆分窗格

        { "command": { "action": "splitPane", "split": "horizontal"}, "keys": "alt+shift+-" }, // 拆分窗格

        { "command": { "action": "splitPane", "split": "vertical"}, "keys": "alt+shift+plus" }, // 拆分窗格

        { "command": { "action": "copy", "singleLine": false }, "keys": "ctrl+c" }, // 复制

        { "command": { "action": "copy", "singleLine": false }, "keys": "ctrl+shift+c" }, // 复制

        { "command": { "action": "copy", "singleLine": false }, "keys": "ctrl+insert" }, // 复制

        { "command": "paste", "keys": "ctrl+v" }, // 粘贴

        { "command": "paste", "keys": "ctrl+shift+v" }, // 粘贴

        { "command": "paste", "keys": "shift+insert" }, // 粘贴

        { "command": "scrollUp", "keys": "ctrl+shift+up" }, // 向上滚动

        { "command": "scrollDown", "keys": "ctrl+shift+down" }, // 向下滚动

        { "command": "scrollUpPage", "keys": "ctrl+shift+pgup" }, // 向上滚动一整页

        { "command": "scrollDownPage", "keys": "ctrl+shift+pgdn" }, // 向下滚动一整页

        { "command": { "action": "adjustFontSize", "delta": 1 }, "keys": "ctrl+=" }, // 调整字号

        { "command": { "action": "adjustFontSize", "delta": -1 }, "keys": "ctrl+-" }, // 调整字号

        { "command": "resetFontSize", "keys": "ctrl+0" }, // 重置字号

        //{ "command": "unbound", "keys": "ctrl+q" } // 取消绑定键

        { "command": "toggleFocusMode", "keys": "shift+f11" }, // 对焦模式

        { "command": "toggleAlwaysOnTop", "keys": "alt+shift+tab" }, // 始终处于顶部模式

        { "command": { "action": "setTabColor", "color": "#ffffff" }, "keys": "ctrl+a" }, // 设置选项卡颜色

        { "command": "openTabColorPicker", "keys": "ctrl+b" }, // 打开选项卡颜色选取器

        { "command": "renameTab", "keys": "ctrl+c" }, // 重命名选项卡

        { "command": "toggleRetroEffect", "keys": "ctrl+d" }, // 切换复古终端效果

        { "command": "commandPalette", "keys": "ctrl+shift+p" } // 命令调色板
    ]
}

ctags

ctags的功能:扫描指定的源文件,找出其中所包含的语法元素,并将找到的相关内容记录下来。

####1 查看ctags支持的语言
ctags –list-languages

####2 查看语言和扩展名的对应关系
ctags –list-maps

####3 查看ctags可以识别和记录的语法元素
ctags –list-kinds

单独查看可以识别的C++的语法元素:

[chuxing@hostname ~]$ ctags --list-kinds=c++
c  classes
d  macro definitions
e  enumerators (values inside an enumeration)
f  function definitions
g  enumeration names
l  local variables [off]
m  class, struct, and union members
n  namespaces
p  function prototypes [off]
s  structure names
t  typedefs
u  union names
v  variable definitions
x  external and forward variable declarations [off]
对当前目录下所有ctags支持的语言格式文件生成tags

ctags -R *

缺点很明显,tags会非常大,tags生成会非常慢,而且代码跳转会卡顿。

只对特定文件生成tags

ctags find -name "*.h"

使用tags

tag命令
用于跳转到指定的tag。例如:

tag tagname

使用这个命令可以跳转到tagname的定义处,即使它在另一个文件中。

快捷键Ctrl+]
取出当前光标下的word作为tag的名字并进行跳转。

tags命令
列出曾经访问过的tag的列表

快捷键Ctrl+T
跳转到前一次的tag处。

stag命令
stag tagname

分割当前窗口,并且跳转到指定的tag。

快捷键Ctrl+W+]
分割当前窗口,并且跳转到光标下的tag。

同名tag
如果存在多个同名的tag,tag命令会给出一个tag的列表,可以通过键入tag的序号来选择tag;也可以通过tselect来过滤tag,如::tselect tagname

如果要在多个tag间移动,可以使用如下命令:

:tfirst             go to first match
:[count]tprevious   go to [count] previous match
:[count]tnext       go to [count] next match
:tlast              go to last match

如果没有指定[count],默认是1。

其他

如果是多个tags文件,可以通过设置tags选项来引入更多的tags文件。例如: :set tags=./tags, ./../tags, ./*/tags
使用tag命令时,可以输入部分tag名,然后使用Tab键进行补全。

打开文件时启动分屏

使用Vim打开文件时,可以通过参数-On 或 -on来启动分屏。

n 代表整数,表示将整个屏幕分成n部分

大写 O 表示进行垂直方向分屏,小写 o 表示水平方向进行分屏

Vim内部启动分屏

使用Vim打开文件后,仍然可以在尾行模式通过以下命令进行屏幕分割

垂直分屏并打开一个新文件

:vsplit filename 或缩写形式 :vsp filename

v 表示单词 vertical,是中文垂直的意思

水平分屏并打开一个新文件

Vim尾行模式下执行命令 :split filename 或缩写形式 :sp filename 

垂直分隔当前打开的文件

Vim命令行模式下执行命令 Ctrl+w v 可将当前打开的文件进行垂直分割

上述命令 Ctrl+w v 的意思是:先同时按键 Ctrl 和 w,再按键 v

水平分隔当前打开的文件

ctrl+w s 可将当前打开的文件进行水平方向分割

上述命令 Ctrl+w s 表示先同时按键 Ctrl 和 w,再按键 s

分屏大小

命令 Ctrl+w = 表示设置所有的分屏幕都有相同的高度

命令 Ctrl+w + 用于增加当前屏幕的高度

命令 Ctrl+w - 用于减少当前屏幕的高度

关闭Vim分屏

ctrl +w c

执行命令

vim 中执行命令

:!ls

WSL_X11_RemoteLogin

sudo apt-get update && sudo apt-get upgrade -y && sudo apt-get upgrade -y && sudo apt-get dist-upgrade -y && sudo apt-get autoremove -y

sudo apt-get install xorg

sudo apt-get install xfce4

sudo apt-get install xrdp

sudo sed -i s/port=3365/port=3365/g /etc/xrdp/xrdp.ini

sudo echo xfce4-session >~/.xsession

sudo service xrdp restart


[....]Restarting Remote Desktop Protocol server: xrdp-sesman xrdp
[20201124-19:34:09] [DEBUG] Testing if xrdp can listen on 0.0.0.0 port 3389.
[20201124-19:34:09] [DEBUG] Closed socket 6 (AF_INET6 :: port 3389)
. ok


远程登录 $(IP):3389

It works.


window10 玩转unbuntu 子系统安装WSL 图形界面,远程桌面

:)

OPENWRT编译之树莓派4B

环境配置说明

1
2
3
4
5
6
7
8
9
# 安装编译工具
sudo apt-get update
sudo apt-get install build-essential asciidoc binutils bzip2 \
gawk gettext git libncurses5-dev libz-dev patch unzip zlib1g-dev \
lib32gcc1 libc6-dev-i386 subversion flex uglifyjs libssl-dev upx \
gcc-multilib p7zip p7zip-full msmtp texinfo libglib2.0-dev xmlto \
git-core qemu-utils libelf-dev autoconf automake libtool autopoint \
curl wget device-tree-compiler rsync

获取编译源码

  1. 注意:不要使用root用户编译,最好使用梯子来加速源码的下载速度
  2. 编译完成后把bin/targets/brcm27xx/bcm2711/openwrt-bcm27xx-bcm2711-rpi-4-ext4-factory.img.gz解压后的img文件刷入SD卡中即可
  3. 可选lean版魔改源码替换官方源码:https://github.com/coolsnowwolf/lede
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 设置代理来加速源码下载,没有代理可跳过或根据需求设置
# export all_proxy="127.0.0.1:7890"

# 获取openwrt官方源码
mkdir openwrt
cd openwrt/
git clone https://git.openwrt.org/openwrt/openwrt.git ./

# 以后每次编译前建议执行以下三行命令更新源码
git pull
./scripts/feeds update -a
./scripts/feeds install -a

make defconfig # 测试编译环境
make menuconfig # 进入固件配置界面
make download -j8 V=s # 下载所需源码,请尽量使用梯子
make -j1 V=s # 首次编译推荐用单线程

# 再次编译前建议使用make clean清理
make clean # 清除bin目录
make dirclean # 清除bin目录和交叉编译工具及工具链目录
make distclean # 清除所有相关的东西,包括下载的软件包,配置文件,feed内容等

可选内核配置

1
2
3
4
5
6
7
8
# 额外配置内核参数,一般不需要配置
# 只能包含到内核而不能作为模块,因为编译后的模块不会添加到固件内
make kernel_menuconfig # 进入内核配置界面

# 修改的内核参数会保存到openwrt/target/linux/bcm27xx/bcm2711/config-5.4
# 和openwrt/target/linux/generic/config-5.4合成最终内核配置文件
# openwrt/build_dir/target-aarch64_cortex-a72_musllinux-bcm27xx_bcm2711/linux-5.4.42/.config

固件编译配置

  1. 简单的make menuconfig参数配置,除必选配置外的其他项可根据需求自行选择

  2. 基础配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 必选配置
Target System -> Broadcom BCM27xx
Subtarget -> BCM2711 boards (64 bit)
Target Profile -> Raspberry Pi 4B

# 镜像参数
Target Images -> ext4 # ext4格式的固件可方便地调整分区大小
Target Images -> squashfs # squashfs格式的固件可恢复出厂设置
Target Images -> Kernel partition size = 64 # boot分区大小为64M
Target Images -> Root filesystem partition size = 512 # root分区大小为512M

# 可选工具
Base system -> block-mount # 在LuCI界面添加<挂载点>菜单
Base system -> blockd # 自动挂载设备
Base system -> wireless-tools # 无线扩展工具
Administration -> htop # 添加htop命令
Firmware -> xxx # 选择你需要的网卡固件,默认即可

  1. 内核模块
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 文件系统
Kernel modules -> Filesystems -> kmod-fs-ext4
Kernel modules -> Filesystems -> kmod-fs-ntfs
Kernel modules -> Filesystems -> kmod-fs-squashfs
Kernel modules -> Filesystems -> kmod-fs-vfat
Kernel modules -> Filesystems -> kmod-fuse

# 网卡支持
Kernel modules -> Network Devices -> kmod-xxx # 有线网卡支持,跟以下几项可根据需求选择性添加
Kernel modules -> Wireless Drivers -> kmod-rt2800-usb # 添加Ralink RT5370芯片的USB无线网卡驱动
Kernel modules -> USB Support -> kmod-usb-net -> kmod-usb-net-sr9700 # 添加USB2.0的有线网卡SR9700芯片支持
Kernel modules -> USB Support -> kmod-usb-net -> kmod-usb-net-rtl8152 # 添加USB2/3的有线网卡RTL8152/3芯片支持
Kernel modules -> USB Support -> kmod-usb-net -> kmod-usb-net-asix # 添加支持亚信的有线网卡支持
Kernel modules -> USB Support -> kmod-usb-net -> kmod-usb-net-asix-ax88179 # 添加USB3.0的有线网卡芯片AX88179的驱动

# USB支持
Kernel modules -> USB Support -> kmod-usb-core # 启用USB支持
Kernel modules -> USB Support -> kmod-usb-hid # USB键鼠支持
Kernel modules -> USB Support -> kmod-usb-ohci # 添加OHCI支持
Kernel modules -> USB Support -> kmod-usb-uhci # 添加UHCI支持
Kernel modules -> USB Support -> kmod-usb-storage # 启用USB存储
Kernel modules -> USB Support -> kmod-usb-storage-extras
Kernel modules -> USB Support -> kmod-usb-usb2 # 开启USB2支持
Kernel modules -> USB Support -> kmod-usb-usb3 # 开启USB3支持

  1. LuCI配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# LuCI设置
LuCI -> Collections -> luci # 开启luci
LuCI -> Modules -> Translations -> Chinese(zh-cn) # 中文支持
LuCI -> Themes -> luci-theme-material # 添加主题

# LuCI应用
LuCI -> Applications -> luci-app-aria2 # 下载工具
LuCI -> Applications -> luci-app-firewall # 防 火 墙
LuCI -> Applications -> luci-app-hd-idle # 硬盘休眠
LuCI -> Applications -> luci-app-opkg # 软 件 包
LuCI -> Applications -> luci-app-qos # 服务质量
LuCI -> Applications -> luci-app-samba4 # 网络共享
LuCI -> Applications -> luci-app-frpc # 内网穿透
LuCI -> Applications -> luci-app-shadowsocks-libev # 翻墙软件
LuCI -> Applications -> luci-app-upnp # UPnP服务
LuCI -> Applications -> luci-app-wol # 网络唤醒
......

  1. 其他工具
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Network -> Download Manager -> ariang	# Aria2管理页面
Network -> File Transfer -> Aria2 Configuration -> *** # 选择Aria2支持的功能
Network -> File Transfer -> curl # 添加curl命令
Network -> File Transfer -> wget # 添加wget命令
Utilities -> Compression -> bsdtar # tar打包工具
Utilities -> Compression -> gzip # GZ 压缩套件
Utilities -> Compression -> xz-utils # XZ 压缩套件
Utilities -> Compression -> unzip # zip解压工具
Utilities -> Compression -> zip # zip压缩工具
Utilities -> Disc -> fdisk # 磁盘分区工具
Utilities -> Disc -> lsblk # 磁盘查看工具
Utilities -> Editors -> vim # vim编辑器
Utilities -> Filesystem -> ntfs-3g # NTFS读写支持
Utilities -> Filesystem -> resize2fs # 分区大小调整
Utilities -> Terminal -> screen # 添加screen
Utilities -> pciutils # 添加lspci命令
Utilities -> usbutils # 添加lsusb命令

  1. IPv6支持
1
2
3
4
5
6
Global build settings -> Enable IPv6 support in packages	# 启用IPv6项
Network -> odhcp6c # IPv6客户端
Network -> odhcpd-ipv6only # IPv6服务端
Network -> Firewall -> ip6tables # IPv6防火墙
LuCI -> Protocols -> luci-proto-ipv6 # WebUI支持

手动配置网卡

  1. 用网线连接自己的电脑和树莓派,LEDE默认的IP为静态 192.168.1.1,可以将电脑网卡设置为静态IP:192.168.1.2 来访问树莓派上的LEDE管理界面。

  2. 设置2.4G无线:网络 -> 无线 选项卡中点修改,基本设置中设置为Legacy模式,频宽2.4GHz和信道自选(切勿使用自动信道和自动频宽),高级设置中国家代码AU。接口配置中模式:接入点AP,网络:lan,然后设置无线安全加密WPA2-PSK和密码等,其余默认即可。

  3. 设置5G无线:网络 -> 无线 选项卡中点修改,基本设置中设置为AC模式,只能使用36信道和频宽为20Mhz或者40Mhz才能用作AP(切勿使用自动信道和自动频宽),高级设置中国家代码AU。接口配置中模式:接入点AP,网络:lan,然后设置无线安全加密WPA2-PSK和密码等,其余默认即可。

  4. 设置WAN口 网络 -> 接口 选项卡中添加一个新接口命名为”wan”,协议根据自己的网络情况自行选择(我的是DHCP客户端),在 物理设置 中单选接口为eth0,先保存但别应用。设置LAN口 网络 -> 接口 选项卡中编辑lan网卡的物理设置,在无线网络和自定义接口上打上钩填上”eth0.1”, 并取消原本eth0前的钩后保存。

自动配置网卡

在openwrt目录下新建一个名为files的文件夹,openwrt在编译的时候,会把files文件夹里的文件编译到固件的根目录。
在files/etc/config/中新建两个文件:network,wireless内容如下用来分别配置接口和无线

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# openwrt/files/etc/config/network

config interface 'loopback'
option ifname 'lo'
option proto 'static'
option ipaddr '127.0.0.1'
option netmask '255.0.0.0'

config globals 'globals'
option ula_prefix 'fd38:13ae:ceeb::/48'

config interface 'lan'
option type 'bridge'
option proto 'static'
option ipaddr '192.168.1.1'
option netmask '255.255.255.0'
option ip6assign '60'
option ifname 'eth0.1'
option _orig_ifname 'eth0 wlan0'
option _orig_bridge 'true'

config interface 'wan'
option ifname 'eth0'
option proto 'dhcp'
option _orig_ifname 'erspan0'
option _orig_bridge 'false'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# openwrt/files/etc/config/wireless

config wifi-device 'radio0'
option type 'mac80211'
option channel '36'
option hwmode '11a'
option path 'platform/soc/fe300000.mmcnr/mmc_host/mmc1/mmc1:0001/mmc1:0001:1'
option htmode 'VHT40'

config wifi-iface 'default_radio0'
option device 'radio0'
option mode 'ap'
option encryption 'none'
option ssid 'RPI4'
option network 'lan'

其他实用技巧

  1. 系统 -> LED配置中:LED0是绿色灯,LED1是红色灯,可以用来当无线收发的指示灯
  2. 使用:cat /sys/class/thermal/thermal_zone0/temp 查看CPU温度
  3. 在Samba中使用root用户除了执行smbpasswd -a root添加用户外,还需要注释模板中的:#invalid users = root
  4. 使用Win10 WSL环境编译的,编译前建议先将Win10系统变量剔除,否则可能报错:export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
  5. 单核编译大概需要4个小时,中间可能会有几次错误,有的错误可跳过对后续编译没有影响
  6. 在OpenWRT的 .config 文件中内核的选项都是形如 CONFIG_KERNEL_XXX 。自己手动添加内核选项时不要忘了在中间添加 _KERNEL_ 前缀。
  7. Goproxy代理失败报错的解决方法:export GO111MODULE=onexport GOPROXY=https://goproxy.cn
1
2
go: github.com/armon/go-socks5@v0.0.0-20160902184237-e75332964ef5: Get "https://proxy.golang.org/github.com/armon/go-socks5/@v/v0.0.0-20160902184237-e75332964ef5.mod": dial tcp 172.217.27.145:443: connect: connection refused