芯片验证中linux的用法详解

电子说

1.3w人已加入

描述

0.前言及文章标题截图

本文主要针对芯片验证工作中常用的linux知识做了一个总结和梳理,内容虽然比较基础,但确实是非常实用。全文8000多字,为了方便大家阅读和查阅,我把文章的目录截图放下面。如果您是老手,看看目录是不是都掌握了;如果您是新手,也不用焦虑,山高千仞,只登一步。

命令

命令

命令

命令

命令

命令

1.shell相关

作为一名芯片验证工程师,几乎每天都在跟shell打交道,如果没有这些基本功,出现一点问题就找IT或同事帮忙,不仅影响工作效率,而且还可能会被严重鄙视的。

1.1查看所有的shell:cat  /etc/shells

命令

1.2查看当前使用的shell:

echo$SHELL,是非常不靠谱的;env| grep SHELL,更加的不靠谱的;echo $$ 得到process_id,然后ps -ef | grep process_id, 也是不靠谱的;

1.2.1 最简单的命令:echo $0

下面介绍一下$0,在linux中,$0表示当前运行的进程名称。大多数情况下使用echo $0来查询当前使用的SHELL是最简单的方法。

命令

命令

但是,echo $0,并不是100%靠谱的。

1.2.2最靠谱的命令:ps  -p “$$”

通过 $$ 获取当前 shell 实例的 PID ,然后通过 ps 命令寻找该 PID所对应的进程。结果中的 CMD 列,会列出当前 shell 程序的名称。

命令

命令

1.3shell间的切换

1.3.1切换到bash

在terminal中直接输入:bash即可。

命令

1.3.2切换到csh

在terminal中直接输入:csh即可。

命令

1.3.3切换到ksh

在terminal中直接输入:ksh即可。

命令

如果 ~/.bash_profile中有export PS1='[u@h w]$',那么bash就不能切换到csh

1.4shell中显示全路径

1.4.1bash中显示全路径

如下图所示,在~/.bashrc文件中,添加下面截图中的内容。

命令

这个命令提示符格式是由PS1这个环境变量控制的,所以我们可以通过修改这个变量来达到我们的目的。

命令

补充:PS1各个字段的含义如下:

u :当前用户的账号名称;

h :仅取主机的第一个名字,如icer.linux,则为icer,.linux则被省略;

d :代表日期,格式为weekday month date,例如:”Mon Aug 1”

:显示时间为24小时格式,如:HH:MM:SS

v :BASH的版本信息

w :完整的工作目录名称。家目录会以 ~代替

W :利用basename取得工作目录名称,所以只会列出最后一个目录

$ :提示字符,如果是root时,提示符为:# ,普通用户则为:$

1.4.2csh中显示全路径

如下图所示,在~/.cshrc文件中,添加下面截图中的内容。

命令

1.5basename[感谢关注微信公众号《芯片验证日记》]

有些项目的脚本中,经常会出现basename,具体的用法可以通过:man basename

或者basename –help查看解释,还有例子,非常友好。

命令

basename可以获取末尾路径名或文件名

命令

basename可以获取末尾目录名或者文件名:

命令

命令

1.6$0/$1-9/$#/$?/$*/$@/$!/$-/$IFS的用法

为什么会详细地介绍下面这些奇怪的符号?作为一名芯片验证工程师,经常会接触到各种各样的shell脚本,这些可都是芯片验证工作必需的基本功呀!

1.6.1 $0 :脚本名

返回当前执行的shell脚本的名称。

1.6.2 $1-$9 :分别代表第1-9个参数

分别代表脚本执行命令的第1个参数、第2个参数……第9个参数。

命令

命令

1.6.3$# :表示参数的个数。

命令

执行脚本的结果:

命令

1.6.4$* :表示所有参数

命令

命令

1.6.5$@ :表示所有参数

命令

命令

1.6.6$* 和 $@ 的区别:

区别在于,如何将参数作为单个字符串或多个独立字符串进行处理。

$*会把所有的参数解释成一个单词(单个字符串),即每个参数之间不会加上空格,全部组合成一个字符串,用"IFS"(默认是空格)分隔。所以,将*放在双引号里,预处理$符号,保持长字符串的完整性。

$@会把所有的参数看成是独立的单词(多个独立的字符串),即每个参数之间加上空格,将每个参数作为一个独立的字符串处理。

试验代码,如下图所示:

命令

  运行结果,如下图所示:

命令

从上面的实验可以看出,使用∗时,所有参数都解释为单个字符串,由空格分隔。而使用@时,每个参数都被解释为一个单独的字符串,并独立处理。在大多数情况下,使用$@是更加灵活和安全的选项,因为它可以独立处理每个参数,而不会将它们合并为单个字符串。

1.6.7$? :上一个命令的退出状态码

命令

命令

输出结果0,表示上一个命令执行成功。

1.6.8$$ :当前进程ID号

获取当前正在运行的Shell脚本的进程ID(PID)。使用$$变量时,需要注意它只能获取当前Shell脚本的PID而不能获取任何子进程或后台任务的PID。

命令

测试代码,如下图所示:

命令

运行结果,如下图所示:

命令

1.6.9 $!  :最近一次在后台运行的进程的PID号

在LinuxShell脚本中,!是一个特殊变量,用于获取最近一次在后台运行进程的PID号(进程ID号)。! 通常用于在脚本中启动后台进程,并且需要获取后台进程的PID号。

测试代码,如下图所示:

命令

运行结果,如下图所示:

命令

1.6.10$- :获取当前Shell的选项标志(Option Flags)

选项标志是Shell用来控制其行为的一些特殊设置。$- 可以用来获取当前Shell所使用的选项标志,通常应用于Shell脚本的调试中,可以帮助我们诊断问题。

命令

上述输出中,选项标志中包含了5个字符,分别表示以下内容:

h:bash shell启用hash命令时将完成命令名和缓存条目之间的HASH值打印到标准错误输出中;

i:交互模式运行,即标准输入与终端相连;

m:启用作业控制功能;

B:启用Brace Expansion(花括号扩展)机制;

H:Shell扩展历史记录功能,寻找法:$HOME/.bash_history,如果该文件不存在则新建一个。

1.6.11$IFS :指定Shell脚本中的字段分隔符

字段分隔符是将一行输入或输出按照不同的字段拆分开来并存储在不同的变量中的标记。默认情况下,$IFS的值为空格,制表符和换行符。但是,我们可以将其设置为其他的分隔符来满足特定的需求。

下图中的脚本,通过read命令读取一行输入,并通过将$IFS设置为逗号来将输入行分隔成不同的变量。最后,使用for循环按顺序输出不同的变量。

命令

命令

这是一个非常有用的用法,可以将一行以逗号或其他字符分隔的值按分隔符分成不同的变量,进一步处理这些变量值。

2.系统查询相关[感谢关注微信公众号《芯片验证日记》]

为什么会介绍这些命令?因为有些eda软件对操作系统OS是有依赖性的,当eda软件出现一些很怪异现象的时候,也许是软件版本和OS不兼容导致的,这时候可以查一下eda软件的releasenote,然后对比一下os信息,看看是否匹配。

2.1lsb_release -a

查看当前Linux 系统完整的版本信息,包括Linux 系统的名称和对应的版本号,以及该版本的代号。

命令

2.2cat /etc/redhat-release

命令

2.3cat /proc/cpuinfo |grep processor

查看cpu信息

命令

2.4top法查看cpu信息

首先执行top命令;然后在top命令的显示界面,按数字键1,即可查看到当前系统中的总cpu数。

命令

2.5lscpu

命令

2.6cat /proc/meminfo

命令

2.6free -h|free -m|free -g

命令

free-m以兆字节为单位显示,free -g 以G字节为单位显示

命令

2.7uptime

查询系统时间。有时候server上的时间跟我们生活上的时间并不一致,当通过history查询到某个自己特别care的命令执行时间的时候,这时候如果想知道这个命令被执行的真正时间,那这个命令就派上用场了。

命令

2.8查询账号相关信息

命令

3.进程相关[感谢关注微信公众号《芯片验证日记》]

下面这些命令在工作日常也经常用到,也是基本中的基本。

3.1ps -ef |grep 进程关键字

查找指定进程java: ps -ef | grep java 命令

查找指定进程vsim:

ps-ef |grep vsim

3.2bg和fg命令

linux下如果想一个任务或者程序在后台执行可以使用&,实际上linux还提供了其他任务调度的命令。

bg :将一个在后台暂停的命令,变成继续执行;【background后景;背景;不显眼的位置;底色】,列出已经停止或后台的作业。

fg :将后台中的命令调至前台继续运行,【foreground:前景,重要位置】,将最近的作业带到前台。

fg n:将作业n带到前台。

jobs: 查看当前有多少在后台运行的命令。

ctrl + z:  可以将一个正在前台执行的命令放到后台,并且暂停。

nohup 命令 :不挂断地运行命令。nohup就是不挂起的意思( nohang up)。

3.3杀掉僵尸进程

kill-9 进程id

命令

xkill

通过xkill可以杀死图形程序应用。用法如下图所示,在terminal里面输入xkill回车,会出现一个白/黑色的x, 然后用鼠标单击想要杀死的应用,想杀哪个就用鼠标左键点击哪个,还可以杀自己。

命令

kill-9 -1

终止你拥有的全部进程,功能类似killall -u 用户名

killall 程序名

killallfirefox

注意:该命令可以使用-9 参数来强制杀死进程,killall -9 firefox

killall-u 用户名

killall-u icer #功能类似kill -9 -1

pkill程序名

直接杀死所有进程,比如:

pkillfirefox

pkilljava

kill和pkill的区别:

kill 对应的是 PID,pkill 对应的是COMMAND

PID和COMMAND的关系,如下图所示:

命令

4.环境变量相关[感谢关注微信公众号《芯片验证日记》]

玩eda软件的第一步就是要懂环境变量,基础的不能再基础的知识了。

4.1搜索环境变量的值

bash中搜索环境变量的值:env|grep 环境变量的名字

csh中搜索环境变量的值:setenv|grep 环境变量的名字

命令

命令

4.2增加或查看环境变量

bash中是export;

csh中是setenv

命令

命令

命令

5.压缩和解压命令

5.1tar命令

把文件夹test压缩为test.tar.gz

 

tar -zcvf  /home/icer/test.tar.gz /temp/test #tar -zcvf 目标文件名.tar.gz 源文件名

 

把压缩包解压到特定目录

 

tar -zxvf /home/icer/test.tar.gz-C /temp/ #C—change directory
tar -xvf /home/icer/test.tar.gz  -C  /temp/

 

把压缩包解压到当前目录

 

tar -zxvf /home/icer/data.tar.gz

 

把文件夹打包压缩到当前目录

 

tar -zcvf /home/icer/data.tar.gz /home/test/data

 

解压.tar.xz格式

 

tar -xvJf  data.tar.xz #其中J为大j,其他选项小写

 

5.2zip/unzip命令

 

zip test.zip test

 

命令

 

unzip test.zip

 

命令

5.37za命令

 

7za -x filename.7z

 

6.查磁盘分区和文件夹占用空间

regression跑不下去了,磁盘空间是不是快爆了,分配给自己硬盘空间是不是已经满了,这总得知道吧。

df命令

df -h ./

命令

  df -h ~

命令

du命令

du -sh 目录名

命令

7.ls命令[感谢关注微信公众号《芯片验证日记》]

7.1ls

命令

7.2ls -rtlah

命令

7.3 ls -rtlha |grep "^d" #列出所有的目录

命令

7.4 ls -rtlh |grep"^-"  #列出所有的文件

命令

7.5 ls -rtla|grep "^d" |wc -l   #显示文件夹的数量

命令

7.6 ls –ld  .*  #只显示隐藏文件

命令

8.cd命令[感谢关注微信公众号《芯片验证日记》]

cd ~:返回home目录

cd -:返回前一目录

cd../../ :返回上上级目录

9.mkdir命令

mkdir-p

mkdir -p: 可以一次性创建多重目录,p=parents

 

mkdir -p /home/icer/my_work/mydir
   

 

mkdir-m

mkdir-m=mkdir + chmod

 

mkdir -m 755 ~/auto_run.sh
   

 

10.touch

touch[文件名]

11.chmod

 

chmod 755 ~/my_work/foo.txt

 

12.chown 必须使用root权限操作,将文件~/eda/license.dat的所有者和所属组均修改为icer

 

chown icer:icer ~/eda/license.dat
   

 

13.cp命令

cp [选项] [源] [目标]

 

cp -rf abc mnp
cp -rf *.png *.txt *.sv /home/icer/
cp -rf /user/source/ /home/icer/

 

14.mv命令

mv <-f | -i>  [文件1]  [文件2]

mv <-f | -i>  [目录1]  [目录2]

mv <-f | -i>  [文件列表]  [目录]

-f :如果目标文件已存在,不提示直接覆盖已有文件。

-i :如果目标文件有同名,则先询问是否覆盖已有文件。

 

mv abc yyy
mv /user/source/ /home/icer/des/
mv -i ./nic/*.sv ./flist

 

15.rm命令

rm<选项>  [文件列表]

选项说明:

-r :recursion表示递归,将目录及以下文件逐层删除。

-f :force,

16.wc文件内容统计命令

wc <选项> 文件列表

统计指定文件中的字节数、字数、行数。

-c :character, 统计字节数

-l :line,统计行数

-w :word,统计字数

更多内容请参考,本公众号另外一篇文章 查看整个项目的代码行数  

17.find命令 [感谢关注微信公众号《芯片验证日记》]

find[目录列表] [匹配标准]

 

find . -name “*file*”

 

17.1按名称搜索文件

普通用法

 

find . -name test.txt
  查找所有格式为 pdf 的书籍,使用正则表达式:

 

 


find  ./icer/books  -name  "*.pdf"
 

默认情况下,find 命令会搜索常规文件,但最好进行指定(-type f)以使所有内容更清晰:

 

 


find ./icer/books -type f -name "*.pdf"
 

 

17.2查找不同类型的文件

通过指定 -type 选项来搜索其他类型的文件,例如搜索目录:

 


find . -type d -name "icer*"
#或者符号链接:
find . -type l -name "icer*"
 

17.3 按指定的时间戳查找文件 搜索访问access时间查过7天的

 

 


find . -type f -atime +7
 

查找修改modify时间正好是 5 天前的文件,请不要包含 +,因为它的意思是“大于”。

 

 


find . -type f -mtime 5
 

搜索更改change时间在 5~10 天前的文件:

 

 


find . -type f -ctime +5 -ctime -10
 

 

17.4 按大小查找文件

查找大小为 10 MB ~ 1 GB 的文件:

 


find . -type f -size +10M -size -1G
 

 

17.5 按权限查找文件

搜索所有具有 777 权限的文件,这意味着一个文件对其持有者、组和所有用户具有所有的读、写和可执行权限。

 


find . -type f -perm 777
 

 

17.6 按用户名查找文件

查找所有属于icer的文件:

 


find -type f -user icer
 

 

17.7 在找到文件后执行命令(-exec)

 


find . -type f -atime +365 -exec rm -rf {} ;
上述命令在 -exec 选项后是 rm -rf,其用于删除文件。{} 是用于查找结果的占位符。 注意:占位符{} 非常重要,尤其是在您想删除文件时。因为,如果您不使用它,该命令将对所有文件执行(而不是您刚刚通过find 命令找到的文件)。

 

做一个尝试,在终端上执行以下两个命令,并检查它们的结果有何不同:

 


#一个使用占位符:
find . -type f -atime +5 -exec ls {} ;
#另一个不使用占位符:
find . -type f -atime +5 -exec ls ;
-exec 选项后面的命令必须以分号(;)结束。众所周知,转义字符用于去 除单个字符的特殊含义。在 Linux 中,反斜杠 用作转义字符。所以我们将它用于分号字符。

 

 

17.8常规处理动作 [感谢关注微信公众号《芯片验证日记》]

17.8.1-print

默认的处理动作,显示至屏幕

 

find /  -name  httpd.conf  -print

 

17.8.2-ls

类似于对查找到的文件执行 "ls -l"命令

 

find / -type f -size +1G -ls

 

17.8.3-delete

删除查找到的文件

 

find ~ -type d -empty -delete
find ./ -type f -delete
# 删除大与100M,时间在7天前的文件
find /test -size +100M -mtime +7 -delete

 

17.8.4-fls /path/to/somefile

查找到的所有文件的长格式信息保存至指定文件中。

命令

命令

17.8.5-ok command {} ;

对查找到的每个文件执行由command指定的命令,对于每个文件执行命令之前,都会交互式要求用户确认。

其中的大括号{}作为检索到的文件的占位符,用于引用查找到的文件名称自身,而分号(;)作为命令结束的标志, 需要转义, 也可以用 + 号表示。-exec command {} ; 等同于 -exec command {} +

17.8.6-exec command {} ;

对查找到的每个文件执行由command指定的命令。其中的大括号{}作为检索到的文件的占位符,用于引用查找到的文件名称自身,而分号(;)作为命令结束的标志, 需要转义, 也可以用 + 号表示。-exec command {} ; 等同于 -exec command {} +

几个小例子:

 

find . -type d -maxdepth 1
find /var/mail/ -size +50M -exec rm {} ;
find . -name “*.sv” |xargs rm -rf
find . -name “*.sv” -exec rm -rf {} ;
find -type f | xargs -n 3 rm -rf
find -type f | exec rm -rf {} ;

 

17.8.7忽略大小写

使用-iname参数选项

 

find . -iname "example*" -print

 

17.8.8否定参数

find 也可以用 ! 排除匹配到的模式,下面的find命令能够匹配所有不以.txt结尾的文件。

 

find . ! -name "*.txt" -print #注意!和-name之间有空格

 

17.9find结合xargs

xargs(英文全拼:eXtended ARGumentS)是给命令传递参数的一个过滤器,也是组合多个命令的一个工具。xargs 可以将管道或标准输入(stdin)数据转换成命令行参数,也能够从文件的输出中读取数据。xargs 作为后面命令的参数。

#将find查找的所有文件作为参数传递给grep进行过滤

 

find . -name “*file*” | xargs grep include
# 查找大于20M的文件,并显示具体大小
find ./ -type f -size +20M 2>/dev/null | xargs du -sh

 

命令

 

# 查找大于60M的文件,并显示详细信息
find ./ -type f -size +60M 2>/dev/null | xargs ls -l

 

命令

 

# 查找系统中最大的3个文件
find ./ -type f -exec du -sh {} + 2>/dev/null | sort -rh | head -n 3

 

命令

18.grep命令 [感谢关注微信公众号《芯片验证日记》]

grep:查找文件内容。

 

grep -Rn “xx”,#一定要用R,不要用r,我是吃过亏的。
  18.1pgrep pgrep是一个根据名称查找进程ID的命令,返回的是进程ID,若存在当个进程,则分为不同的行返回ID(默认实现)。

 

命令

pgrep经常和其他命令配合使用,最常见的是kill:

命令

19.tree命令

tree -L 2 文件件名称

命令

20.tee命令

tee的应用场景

向命令执行窗口输出的同时,将内容输出到文件。应用场景:将仿真过程中terminal中显示的内容,输出到特定的文件make run |tee  xxx_tee.log

 

ping baidu.com | tee pb.log
ping baidu.com | tee -a pb.log #追加
ping baidu.com | tee pb.log pb2.log #输出到多个文件
cat pb.log |tee |wc -l #将tee命令的输出重定向为另一个命令的输入流
#在vim打开的文件中输入,:w !sudo tee %   #用tee命令提高写入文件的权限等级
ping baidu.com |tee -i pb.log #让tee命令忽略中断事件

 

与自己对话如何呢,或者叫做复读机?

tee命令直接跟文件的话,会等待输入,并同步进行输出到终端和文件的操作。

$tee test.log

hello

hello

world

world

$cat test.log

hello

world

21.split命令

split命令可以用于切割文件,将大文件切割成几个小文件。

命令

split-C 1M/10G xx.log

命令

22.sed命令

sed主要用来直接处理文本文件。

 

sed -i “s/” a.sv

 

只打印那些发生替换的行

 

sed -n ‘s/uvm_hdl_read////&/p’ *.sv

 

直接修改用下面命令

 

sed -i ‘s/uvm_hdl_force///&/g’ *.sv

 

删除所有空行

 

sed “s/^$/d” foo.sv

 

删除所有只包含空格或者制表符的行

 

sed “s/^[ ] *$/d” foo.sv

 

删除所有引号

 

sed “s/””//g” foo.sv

 

删除所有//注释的行

 

sed “s/////g” foo.sv

 

23.unix2dos命令

unix2dos是将Linux&Unix格式文件转换为Windows格式文件的命令。dos2unix和unix2dos是互为孪生的一个命令,dos2unix是将Windows格式文件转换为Unix、Linux格式的实用命令。Windows格式文件的换行符为 ,而Unix&Linux文件的换行符为 .dos2unix命令其实就是将文件中的 转换为 。在windows下生成的license文件,放到linux中用时会用到该命令。

使用前需要先安装:

 

yum install -y dos2unix
yum install -y unix2dos

 

对单个文件操作:

 

unix2dos test.txt

 

对多个文件操作:

 

unix2dos test1.txt test2.txt test3.txt

 

对整个目录中的文件做unix2dos操作:

 

find /path/to/dir  -type f -exec unix2dos {} ;

 

如果要保持文件时间戳不变,加上-k参数

 

unix2dos -k test1.txt test2.txt

 

24.ln -s软连接 [感谢关注微信公众号《芯片验证日记》]

创建软连接

ln-s [源文件/目录] [目标软链接]

命令

删除软连接

删除软链接和删除文件/目录操作一样,使用rm命令。但是需要特别注意的是,如果只是删除软链接,不想误删除软链接目录真实文件数据,rm目录时路径末尾一定不能带"/"。如果带了"/",会将链接到的路径下的文件全部删除。

命令

25.lsof命令

lsof是linux下非常实用的系统级的监控、诊断工具。它是List Open Files的缩写(lsopen file)。使用 lsof可以获取任何被打开文件的各种信息,因为lsof 需要访问核心内存和各种文件,所以必须以root用户的身份运行它才能够充分地发挥其功能。

26.ftp命令 [感谢关注微信公众号《芯片验证日记》]

格式:ftp[hostname| ip-address]

a)在linux命令行下输入:

 

ftp 192.168.1.1
#or
ftp.company.com

 

b)服务器询问你用户名和密码,分别输入用户名和相应密码,待认证通过即可。

下载文件用get;下载多个文用mget;上传文件用put;上传多个文件用mput

27.sftp命令

sftp user@xxftp.company.com.cn,然后服务器询问你的密码,输入密码,待认证通过即可。

28.如何删除一些奇怪的文件

a)进入奇怪文件所在的文件夹,ls-i 得到inode节点号,然后kill-9 inode节点号;

b)lsof.nfs* 可以找到挂住的进程,kill这个进程,这些隐藏文件就可以删除了。

c)ps-ef |grep “.nfs*” 得到进程id,然后通过kill -9 进程id杀掉即可。

29./dev/null的含义和用途

/dev/是包含所有物理和虚拟设备的目录。例如,/dev/sda 可能是主硬盘驱动器,/dev/sdb可能是正在使用的笔记本驱动器的文件。这就是在 Linux 中访问设备的方式。除了这些物理设备(如硬盘驱动器)之外,Linux还具有虚拟设备。

虚拟设备是充当物理设备的设备,但实际上仅以软件形式存在。应用程序可以从这些设备获取数据,但该数据不是来自物理设备,而是来自/dev/null,/dev/null是一种特殊的虚拟设备,用于写入而不是读取。写入/dev/null的任何内容都会从操作系统中消失。正是由于这个原因,/dev/null 被称为 bitbucket。例如,将"Hello World"输出重定向到/dev/null中。结果就没有任何输出。“Hello World”不存储在系统上的任何文件中。它只是消失了。

/dev/null的使用:

在Linux中运行任何命令时,都会生成两个输出流,即标准输出(stdout)和标准错误(stderr)。标准输出是程序正常生成的任何输出。标准错误包含命令生成的所有错误。stdout和stderr流可以通过它们的文件描述符(分别为 1 和 2)进行访问。

/dev/null与stdout和stderr一起使用:如下图所示,ping xrun.log是不会成功的,所以1>m.txt是有问题的,因为1代表标准输出stdout;这里应该使用2>n.txt,因为2代表标准错误输出,所以,m.txt是空的,n.txt里面存储了标准错误输出的结果。

命令

如下图所示,ping xrun.log 2>/dev/null是丢弃错误信息到/dev/null,系统没有任何提示;ping xrun.log >/dev/null是丢弃正确信息到/dev/null,系统报错。

命令

概括来讲,/dev/null 在Linux中是一个void,它会吸收任何输入,并且不返回任何内容。大多数情况下,管理员使用它来转储无用的数据,在其中输出,这样它就不会占用系统内存和处理能力。甚至可以通过将无用的文件直接移动到/dev/null/ 来删除它们。

审核编辑:汤梓红

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分