Linux常见问题及解决方案汇总,持续更新……
例如:
./mnist_caffe: error while loading shared libraries: libarmnn.so: cannot open shared object file: No such file ordirectory
出现该问题的原因是运行./mnist_caffe
的时候找不到依赖的libarmnn.so
。实际上libarmnn.so
是已经编译好的文件,其所在目录是/home/lg/armnnSDK/armnn
。
解决常用方法有两种,一是执行sudo gedit /etc/ld.so.conf
,然后将libarmnn.so
所在的目录/home/lg/armnnSDK/armnn
加入其中,再执行sudo /sbin/ldconfig
使其生效即可。不过一般对于自己编译生成的文件不这么做,自己编译生成的库一般采用方法二配置路径。二是执行sudo gedit ~/.bash_profile
,然后加入export LD_LIBRARY_PATH=/home/lg/armnnSDK/armnn:$LD_LIBRARY_PATH
。或是如果只在当前终端生效,只执行export LD_LIBRARY_PATH=/home/lg/armnnSDK/armnn:$LD_LIBRARY_PATH
也是可以的。
.o
文件ar -tv libXXX.a
.o
中包含哪些函数objdump -tT libXXX.a
或objdump -tT libXXX.o
ar -rcs libXXX.a A.o B.o
其中A.o
和 B.o
用下面方法生成,指定gcc -c
生成的就是.o
文件:
gcc -c -O3 A.c -I ./
、gcc -c -O3 B.c -I ./
当前目录文件个数:ls -l|grep "^-"| wc -l
当前目录以.o结尾的文件个数:ls -l *.o|grep "^-"| wc -l
当前目录及子目录文件个数:ls -lR|grep "^-"| wc -l
当前目录文件夹包含的文件夹个数:ls -l|grep "^d"| wc -l
当前文件夹及子文件夹包含的文件夹个数ls -lR|grep "^d"| wc -l
find . -name '10-*.jpg' -exec mv {} ../ \;
find . -name '*.xml' -exec mv {} ../img \;
-exec mv {} ../img \;
运行mv
命令;
{}
代表find
到的所有内容;
../
表示移动的目标位置;
\;
表示结束/bin/mv
命令。
对于嵌入式开发往往开发源码在Windows上,编译在Linux上,这时如果将Windows目录挂载到Linux下则会大大提高开发效率。
对于IPC,串口登录IPC,进入IPC根目录/
,一般挂载点选择/mnt
或/tmp
,也可以是其它目录。
mount -t cifs //Windows的IP地址/Windows上要共享文件夹名字 /mnt/挂载点名字 -o username=XXX, password=XXX
例如在windows的D盘建立了文件夹win-mnt
,然后设置了共享,假设Windows的IP地址是10.182.13.58
,挂载方式是:
mount -t cifs //10.182.13.58/win-mnt ./mnt -o username=garylau, password=mypasswd
对于Linux系统其它设备也是类似,在Linux下创建好要挂载的目录(挂载点),将Windows目录挂载到Linux挂载点即可。
删除挂载:umount ./mnt
有时需要Linux下的挂载点不仅有读取的权限还要有写入的权限,此时的指令需要添加dir_mode=07 77,file_mode=0777
,即:
mount -t cifs //Windows的IP地址/Windows上要共享文件夹名字 /mnt/挂载点名字 -o username=XXX,password=XXX,dir_mode=0777,file_mode=0777
如果挂载时报如下错误,则是由于NFS(Network File System,网络文件系统服务器)有多个版本,V2、V3、V4,而且各版本同时运行,因此挂载时需要说明版本号造成的。可通过指定版本号来解决:mount -t cifs //Windows的IP地址/Windows上要共享文件夹名字 /mnt/挂载点名字 -o username=XXX, password=XXX, vers=2.1
。
mount error(121): Remote I/O error
Refer to the mount.cifs(8) manual page (e.g. man mount.cifs)
先下载nfs1219.exe,使用该软件将windows下要共享给linux的目录设置为nfs格式,再使用指令mount -t nfs -o nolock windowsIP:/windows盘符/盘符下路径 mnt/
进行挂载。例如在windows的D盘建立了文件夹win-mnt
,然后使用软件NFS Server添加了共享路径d:\win-mnt
,假设Windows的IP地址是10.182.13.58,挂载方式是:mount -t nfs -o nolock 10.182.13.58:/d/win-mnt mnt/
。
find ./ |xargs grep -ri "VGGNetBody"
如果想只列出文件名则加上 -l
find ./ |xargs grep -ri "VGGNetBody -l"
undefined reference to sqrt
在使用sqrt
等在#include
中的函数时虽然添加了头文件,但是在编译的时候仍然会报 undefined reference to sqrt
的错误,此时在编译的指令中添加-lm
即可,参考此处。
释放系统内存缓存:/proc/sys/vm/drop_caches
每个 Linux 系统有三种选项来清除缓存而不需要中断任何进程或服务。
仅清除页面缓存(PageCache)
sync; echo 1 > /proc/sys/vm/drop_caches
清除目录项和inode
sync; echo 2 > /proc/sys/vm/drop_caches
清除页面缓存,目录项和inode
sync; echo 3 > /proc/sys/vm/drop_caches
查看系统中内存使用情况:/proc/meminfo
进程的内存使用情况:/proc/28040/status
查询内存总使用率:free
查询进程 cpu 和内存使用占比:top
进程消耗内存占比和排序:ps aux –sort -rss
linux下free命令详解
Mem 行(第二行)是内存的使用情况。
Swap 行(第三行)是交换空间的使用情况。
total 列显示系统总的可用物理内存和交换空间大小。
used 列显示已经被使用的物理内存和交换空间。
free 列显示还有多少物理内存和交换空间可用使用。
shared 列显示被共享使用的物理内存大小。
buff/cache 列显示被 buffer 和 cache 使用的物理内存大小。
available 列显示还可以被应用程序使用的物理内存大小。
a. getconf LONG_BIT
b. uname -a
c. uname -r
d. cat /proc/version
简要说明写makefile的基本步骤。
a. 指明搜索路径,例如VPATH=src include
或vpath %.cpp src
、vpath %.h include
等;
b. 指明终极target,例如all: run
;
c. 指明中间目标,例如OBJ = main.o factorial.o hello.o
等;
d. 生成中间目标,例如%.o : %.cpp
等;
e. 指明clear
要执行的操作,例如clean:; rm *.o run
等。
文件名使用通配符
makefile中表示文件名时可以使用通配符。可使用的通配符有:*
,?
,[...]
。但是在makefile中这些通配符并不是可以用在任何地方,makefile中通配符可以出现在一下两种场合:a. 可用在规则的目标、依赖中,make在读取makefile时会自动对其进行匹配处理(通配符展开);b.可出现在规则的命令中,通配符的通配处理是在shell中执行此命令时完成的。
除了这两种情况外的其它上下文中,不能直接使用通配符。而是需要通过函数wildcard
来实现。
本小节主要参考你真的理解内存分配吗?如有不妥请联系修改或删除。
test_virtual_physics_address.hpp
#include
#include
namespace test_virtual_physics_address {
auto main() -> int {
std::cout << "testing test_virtual_physics_address......" << std::endl;
int *p = (int *)malloc(1024*1024*1024);
_sleep(3600000);
std::cout << "------------------------------" << std::endl;
return 0;
}
}
main.cpp
#include "test_virtual_physics_address.hpp"
#include
int main()
{
std::cout << "__cplusplus: " << __cplusplus << std::endl;
test_virtual_physics_address::main();
std::cout << "The end." << std::endl;
}
查看内存使用情况cat /proc/397/status
VmRSS
表示进程使用的物理内存大小,但明明申请了1GB 的内存,为什么只显示使用 10560KB 的内存呢?这就涉及到物理内存与虚拟内存。
物理内存:也就是安装在计算机中的内存条,比如安装了 2GB 大小的内存条,那么物理内存地址的范围就是 0 ~ 2GB。
虚拟内存:虚拟的内存地址。由于 CPU 只能使用物理内存地址,所以需要将虚拟内存地址转换为物理内存地址才能被 CPU 使用,这个转换过程由 MMU(Memory Management Unit,内存管理单元) 来完成。虚拟内存 大小不受 物理内存 大小的限制,在 32 位的操作系统中,每个进程的虚拟内存空间大小为 0 ~ 4GB。
程序中使用的内存地址都是虚拟内存地址,也就是说,通过malloc
函数申请的内存都是虚拟内存。实际上,内核会为每个进程管理其虚拟内存空间,并且会把虚拟内存空间划分为多个区域,如下图所示:
上述各区域的作用:
malloc
申请的内存。段,本质上是把内存上的某一块连续的存储空间,专门存储某一类的数据。之所以能够这么做,是因为 CPU 通过以上几个寄存器,让我们这样的“安排”称为一种可能。CPU 将内存中的某个段的内容当做代码,是因为 CS:IP 指向了那里;CPU 将某个段当做栈,是因为 CS:SP 指向了那里。
brk
指针通过malloc
申请的内存地址是由堆空间分配的(其实还有可能从mmap
区分配,这种情况暂时忽略)。在内核中,使用一个名为brk
的指针来表示进程的堆空间的顶部,如下图2所示:
通过移动brk
指针就可以达到申请(向上移动)和释放(向下移动)堆空间的内存。例如申请1024
字节时,只需要把brk
向上移动1024
字节即可,如下图3所示
事实上,malloc
函数就是通过移动brk
指针来实现申请和释放内存的,Linux 提供了一个名为brk()
的系统调用来移动brk
指针。
malloc
函数只是移动brk
指针,但并没有申请物理内存,虚拟内存地址必须映射到物理内存地址才能被使用。如下图4所示:
虚拟地址首先经过段转换,得到线性地址;然后线性地址再经过分页转换,得到最终的物理地址。具体转换过程如图5所示:
只有触发缺页异常时才会触发申请新的物理内存;缺页异常触发的条件是对(没有映射过的)虚拟地址进行读写操作。Linux 内核会对缺页异常进行修复,修复过程如下:
brk
指针内),如果不在brk
指针内,将会导致 Segmention Fault
错误(也就是常见的coredump
),进程将会异常退出。brk
指针内,那么将此虚拟内存地址映射到物理内存地址上,完成缺页异常修复过程,并且返回到触发异常的地方进行运行。1GB
的内存,但实际上只使用了10560KB
的物理内存。The malloc()
and calloc()
functions return a pointer to the allocated memory, which is suitably aligned for any built-in type.
许多计算机体系结构要求特定的类型必须放在特定的内存地址上。例如它可能要求指针的地址必须是4的倍数或double的地址必须是8的倍数。如果没有这个约束条件,可能会导致运行时硬件异常。有些体系结构是如果齐位条件获得满足便提供最佳效率。
数据对齐分为自然对齐和强制对齐,注意这里讲的对齐是指数据地址的对齐。 自然对齐,各个类型变量的内存地址必须是其类型本身的整数倍。结构体对齐到成员最大长度类型的整数倍。
不同的硬件平台对存储空间的处理上有很大的不同,有些平台对某些类型的数据只能从特定地址开始存取否则就会出错;另外一些平台可能不会出错但会影响处理效率,本来一个指令周期就可以完成的操作,可能需要两个指令周期还需要把数据拼在一起处理。例如,对于从奇数边界去访问unsigned short
型变量,显然不符合对齐的规定。在x86上,类似的操作只会影响效率,但是在MIPS或者sparc上,可能就是一个error,因为它们要求必须字节对齐。
操作系统自己也是这么做的,如下代码展示了栈上(跟堆上变量只是在内存不同区而已)变量地址。
#include
#include
#include
namespace test_align {
auto main() -> int {
std::cout << "testing test_align......\n" << std::endl;
unsigned char a = 0;
std::cout << typeid(a).name() << std::endl;
printf("&a = %p, sizeof(a) = %d\n", &a, sizeof(a));
if(size_t(&a) % sizeof(a) == 0) {
std::cout << "a's address starts with times of sizeof(a)." << std::endl;
}
std::cout << std::endl;
short b = 0;
std::cout << typeid(b).name() << std::endl;
printf("&b = %p, sizeof(b) = %d\n", &b, sizeof(b));
if(size_t(&b) % sizeof(b) == 0) {
std::cout << "b's address starts with times of sizeof(b)." << std::endl;
}
std::cout << std::endl;
int c = 0;
std::cout << typeid(c).name() << std::endl;
printf("&c = %p, sizeof(c) = %d\n", &c, sizeof(c));
if(size_t(&c) % sizeof(c) == 0) {
std::cout << "c's address starts with times of sizeof(c)." << std::endl;
}
std::cout << std::endl;
long d = 0;
std::cout << typeid(d).name() << std::endl;
printf("&d = %p, sizeof(d) = %d\n", &d, sizeof(d));
if(size_t(&d) % sizeof(d) == 0) {
std::cout << "d's address starts with times of sizeof(d)." << std::endl;
}
std::cout << std::endl;
long long e = 0;
std::cout << typeid(e).name() << std::endl;
printf("&e = %p, sizeof(e) = %d\n", &e, sizeof(e));
if(size_t(&e) % sizeof(e) == 0) {
std::cout << "e's address starts with times of sizeof(e)." << std::endl;
}
std::cout << std::endl;
float f = 0;
std::cout << typeid(f).name() << std::endl;
printf("&f = %p, sizeof(f) = %d\n", &f, sizeof(f));
if(size_t(&f) % sizeof(f) == 0) {
std::cout << "f's address starts with times of sizeof(f)." << std::endl;
}
std::cout << std::endl;
double g = 0;
std::cout << typeid(g).name() << std::endl;
printf("&g = %p, sizeof(g) = %d\n", &g, sizeof(g));
if(size_t(&g) % sizeof(g) == 0) {
std::cout << "g's address starts with times of sizeof(g)." << std::endl;
}
std::cout << std::endl;
return 0;
}
}
cmake -G "Visual Studio 15 2017" -A Win32 ..
结果如下:
unsigned char
&a = 0059F743, sizeof(a) = 1
a's address starts with times of sizeof(a).
short
&b = 0059F734, sizeof(b) = 2
b's address starts with times of sizeof(b).
int
&c = 0059F728, sizeof(c) = 4
c's address starts with times of sizeof(c).
long
&d = 0059F71C, sizeof(d) = 4
d's address starts with times of sizeof(d).
__int64
&e = 0059F70C, sizeof(e) = 8
float
&f = 0059F700, sizeof(f) = 4
f's address starts with times of sizeof(f).
double
&g = 0059F6F0, sizeof(g) = 8
g's address starts with times of sizeof(g).
cmake -G "Visual Studio 15 2017" -A x64 ..
结果如下:
unsigned char
&a = 000000B7C39FFA84, sizeof(a) = 1
a's address starts with times of sizeof(a).
short
&b = 000000B7C39FFAA4, sizeof(b) = 2
b's address starts with times of sizeof(b).
int
&c = 000000B7C39FFAC4, sizeof(c) = 4
c's address starts with times of sizeof(c).
long
&d = 000000B7C39FFAE4, sizeof(d) = 4
d's address starts with times of sizeof(d).
__int64
&e = 000000B7C39FFB08, sizeof(e) = 8
e's address starts with times of sizeof(e).
float
&f = 000000B7C39FFB24, sizeof(f) = 4
f's address starts with times of sizeof(f).
double
&g = 000000B7C39FFB48, sizeof(g) = 8
g's address starts with times of sizeof(g).
结构体的自然对齐,成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量类型所占用的字节数的倍数, 且结构的大小为该结构中占用最大空间的类型所占用的字节数的倍数。
char: 偏移量必须为sizeof(char) 即1的倍数
short: 偏移量必须为sizeof(short) 即2的倍数
int: 偏移量必须为sizeof(int) 即4的倍数
float: 偏移量必须为sizeof(float) 即4的倍数
double: 偏移量必须为sizeof(double) 即8的倍数
结构体对齐示例:
#include
#include
namespace test_align {
auto main() -> int {
std::cout << "testing test_align......\n" << std::endl;
typedef struct _ST_A_
{
char c1;
int i;
char c2;
double d;
}stA;
typedef struct _ST_B_
{
char c1;
char c2;
int i;
double d;
}stB;
printf("sizeof double, int, char = %d, %d, %d\n", sizeof (double), sizeof (int), sizeof (char));
printf("sizeof stA = %d, stB = %d\n", sizeof(stA), sizeof(stB));
return 0;
}
}
输出:
sizeof double, int, char = 8, 4, 1
sizeof stA = 24, stB = 16
当结构体中有嵌套符合成员时,复合成员相对于结构体首地址偏移量是复合成员最宽基本类型大小的整数倍。
#include
#include
namespace test_align {
auto main() -> int {
std::cout << "testing test_align......\n" << std::endl;
typedef struct _ST_A_
{
char c1;
int i;
char c2;
double d;
}stA;
typedef struct _ST_C_
{
char c;
stA sta;
}stC;
printf("sizeof double, int, char = %d, %d, %d\n", sizeof (double), sizeof (int), sizeof (char));
printf("sizeof stA = %d, stC = %d\n", sizeof(stA), sizeof(stC));
return 0;
}
}
输出:
sizeof double, int, char = 8, 4, 1
Sizeof stA = 24, stC = 32
#pragma pack(n)
使用指令#pragma pack(n)
,C编译器将按照n
个字节对齐;使用指令#pragma pack()
,取消自定义字节对齐方式
#pragma pack(n)
用来设定变量以n
字节对齐方式,变量存放的起始地址的偏移量:
n
大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式n
小于该变量的类型所占用的字节数,那么偏移量为n
的倍数,不用满足默认的对齐方式。n
大于等于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;否则必须是n
的倍数。示例1:
#include
#include
namespace test_align {
auto main() -> int {
std::cout << "testing test_align......\n" << std::endl;
#pragma pack(1)
typedef struct _ST_A_
{
char c1;
int i;
char c2;
double d;
}stA;
#pragma pack()
// n=2,对于小于2字节的char对齐方式是2;对于大于2字节的int double使用自然对齐
#pragma pack(2)
typedef struct _ST_B_
{
char c1;
int i;
char c2;
double d;
}stB;
#pragma pack()
#pragma pack(3) // [MinGW Makefiles] warning: alignment must be a small power of two, not 3
// [Visual Studio 15 2017] warning C4086: 杂注参数应为“1”、“2”、“4”、“8”或者“16”
typedef struct _ST_C_
{
char c1;
int i;
char c2;
double d;
}stC;
#pragma pack()
#pragma pack(4)
typedef struct _ST_D_
{
char c1;
int i;
char c2;
double d;
}stD;
#pragma pack()
#pragma pack(8)
typedef struct _ST_E_
{
char c1;
int i;
char c2;
double d;
}stE;
#pragma pack()
// n=16,比最大的double字节数还大,则使用自然对齐方式
#pragma pack(16)
typedef struct _ST_F_
{
char c1;
int i;
char c2;
double d;
}stF;
#pragma pack()
typedef struct _ST_DEFAULT_
{
char c1;
int i;
char c2;
double d;
}stDefault;
printf("sizeof stA = %d, stB = %d\n", sizeof(stA), sizeof(stB));
printf("sizeof stC = %d, stD = %d\n", sizeof(stC), sizeof(stD));
printf("sizeof stE = %d, stF = %d\n", sizeof(stE), sizeof(stF));
printf("sizeof stDefault = %d\n", sizeof(stDefault));
return 0;
}
}
输出:
sizeof stA = 14, stB = 16
sizeof stC = 24, stD = 20
sizeof stE = 24, stF = 24
sizeof stDefault = 24
注意上面#pragma pack(3)
时应该是使用了自然对齐方式,而不是自定义的3
。
示例2:
#include
#include
namespace test_align {
auto main() -> int {
std::cout << "testing test_align......\n" << std::endl;
#pragma pack(8)
struct s1
{
short a;
long b;
};
struct s2
{
char c;
s1 d;
long long e;
};
struct s3
{
char c;
short a;
long b;
long long e;
};
#pragma pack()
printf("sizeof s1 = %d\n", sizeof(s1));
printf("sizeof s2 = %d\n", sizeof(s2));
printf("sizeof s3 = %d\n", sizeof(s3));
return 0;
}
}
(Visual Studio 15 2017)输出:
sizeof s1 = 8
sizeof s2 = 24
sizeof s3 = 16
例如将anaconda3的bin路径添加到环境变量:
gedit ~/.bashrc
添加如下内容:
# 添加anaconda3路径
export PATH=/home/lg/05.Softwares/anaconda3/bin:$PATH
然后执行:
source ~/.bashrc
sudo apt-get remove flameshot
,flameshot是一款截图软件。
df -k 目录
,例如df -k /home
由下图可知home
目录挂载在磁盘/dev/nvme1n1p3
上,挂载点是根目录/
。
cat /etc/group
lspci | grep -i nvidia
或者ubuntu-drivers devices
查看驱动版本sudo dpkg --list | grep nvidia-*
或cat /proc/driver/nvidia/version
查看ubuntu系统发布版本号
cat /etc/issue
或lsb_release -a
查看内核版本号uname -sr``uname -a
查看CPU个数cat /proc/cpuinfo | grep "physical id" | uniq | wc -l
查看CPU核数cat /proc/cpuinfo | grep "cpu cores" | uniq
查看CPU型号cat /proc/cpuinfo | grep 'model name' |uniq
GPU列表信息nvidia-smi
显示显卡信息nvidia-settings
查看显卡型号lshw -c video
sudo apt-get install unity-control-center
sudo apt-get install gnome-control-center