signal(SIGPIPE, SIG_IGN);
2、利用send函数最后一个flag参数,
send_len = send(client_fd, ptr, len, MSG_NOSIGNAL);
程序继续运行,于是我们也可以根据,send_len来判断异常,并且利用errno来获取具体的异常信息
send_len = send(client_fd, ptr, len, MSG_NOSIGNAL);
if(send_len < 0)
{
switch(errno)
{
case EPIPE:
{
do;
break;
}
case EINTR:
{
do;
break;
}
case EAGAIN:
{
do;
break;
}
default:
{
do;
break;
}
}
}
LINUX socket connect 奇怪的错误(eg:operation now in process)
如果是在connect 之前设置的非阻塞套接字,那么connect 没等连接成功就返回了,此时返回的错误码不一定是正确的,从而会导致出现奇奇怪怪的错误,误导问题定位
diff 与patch
这个功能在协作开发的时候使用比较方便,
diff -ru oldfile newfile > xxx.patch (r递归,u输出好看点)
patch -p1 < xxx.patch (p1 p0 啥的上网搜)
QT检测剪贴板内容变化
QClipboard *cb = QApplication::clipboard(); 可以获取到系统剪贴板
connect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(deal()));
QClipboard 有自定义的信号,绑定一下对应的槽函数即可(不知道为啥网上关于qt剪贴板的资源好少,自己在qt帮助文档里看到的)
未整理的杂项
xdg-user-dir DESKTOP 查看桌面目录
xdg-user-dir 查看Home目录
xdg-open url 以系统默认浏览器打开指定url
xdg-mime query filetype /home/user/1.doc 查询指定文件的文件类型
xdg-mime default xx.desktop text/plain 指定文件类型设置默认打开方式
xdg-setting get default-web-browser 查询系统默认浏览器(目前验证麒麟可以,但是UOS 查询会出问题,可能跟UOS 的桌面环境相关)
以后需要执行什么操作,
可以着重去查找xdg下是否有这些操作
(是不是以前做的锁屏之类的命令也是?可拓展一下)
grep -E “pattern_1|pattern_2” 匹配多个字符串
grep -lZ | xargs -0 可以处理带有空格的文件名
列出当前所有的会话
loginctl list-sessions
锁定/解锁会话(如果会话支持屏幕锁)
如果指定了会话ID,那么将锁定/解锁指定会话,否则将锁定/解锁当前调用者的会话
loginctl lock-session [ID]
loginctl unlock-session [ID]
锁定/解锁所有支持屏幕锁的会话
loginctl lock-sessions
loginctl unlock-sessions
linux下 alternatives命令常用于同一个系统中安装同一软件的多个版本
/usr/share/applications 下放置xxx.desktop 可以让linux 所有用户在开始菜单栏中查看到应用
在/home/user/.local/share/applications 下放置xxx.desktop 只能让当前用户在开始菜单栏中查看到
mime匹配的desktop同理,
创建新的desktop文件到指定目录后,执行更新命令:(好像不执行也能识别)
update-desktop-database /usr/share/applications
快捷方式文件内容:
“[Desktop Entry]\n”
“Encoding=UTF-8\n”
“Name=%s\n”
“Exec=%s %d %s\n”
“Icon=%s/%s\n”
“StartupNotify=false\n”
“Type=Application\n”
“Categories=Application;\n”
“Company=sangfor\n”
“Name[zh_CN]=%s\n”
Name[zh_CN] 和Name字段同时存在时,以zh_CN显示的为准,并且对快捷方式进行重命名时,系统会修改zh_CN的值,但不影响Name的值
此外,目前麒麟上对快捷方式重命名会导致文件名跟随变化,UOS 文件名不受影响
mime匹配文件内容:
“[Desktop Entry]\n”
“Categories=Utility;TextEditor\n”
“Name=%s\n”
“Exec=%s %d %s %%F\n”
“Icon=%s/%s\n”
“MimeType=application/msword;application/pdf;”
“application/vnd.ms-powerpoint;”
“application/vnd.ms-excel;”
“application/vnd.openxmlformats-officedocument.wordprocessingml.document;\n”
“StartupNotify=false\n”
“Type=Application\n”
“author=lyg\n”
可以自己添加字段author=lyg, 并不报错,用来识别自己的文件
NoDisplay字段等于true 可以设置菜单不显示,但是右键可以选择
Hidden 字段等于true ,菜单也不显示,右键也不显示
xdg系列的工具:
RHEL 6 和 ubuntu 採用了 FreeDesktop.org 的規格,
官方網站 http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
定義了基本的 Linux 下的 X Window System (X11) 以及其他 Unix-like 作業系統的桌面環境.
主要是為了增加 free software desktop environments 的互通性,
而這環境簡稱為 XDG(X Desktop Group)
比如目前使用过的
xdg-user-dir 获取home目录
xdg-user-dir DESKTOP 获取桌面目录
xdg-open 使用默认程序打开指定的东西。比如使用默认的浏览器打开指定的网址 xdg-open https://127.0.0.1
关注并了解一下这两个宏,和system执行shell成功与否相关
(WIFEXITED(ret) && WEXITSTATUS(ret) == 0)
两个比较好的system处理
// 使用此宏时,需定义 int sysRet; 用来保存返回值。
// 避免 定义 sys_status 变量,导致名字冲突。
#define SYSTEM(cmd)
do {
if ((cmd) == NULL)
{
LOGI(“[SYSTEM] cmd is NULL”);
}
int sys_status = system((cmd));
if (sys_status == -1)
{
LOGI(“[SYSTEM] cmd(%s) status(-1)”, (cmd));
sysRet = -1;
}
else if (!WIFEXITED(sys_status))
{
LOGI(“[SYSTEM] cmd(%s) status(%d) WIFEXITED false”, (cmd), sys_status);
sysRet = -1;
}
else if (WEXITSTATUS(sys_status) != 0)
{
LOGI(“[SYSTEM] cmd(%s) status(%d) WEXITSTATUS false”, (cmd), sys_status);
sysRet = WEXITSTATUS(sys_status);
}
else
{
sysRet = 0;
}
} while(0)
#endif
int do_system(const char *fmt, …)
{
char cmd[BUFSIZ] = “”;
va_list ap;
va_start(ap, fmt);
int num = vsnprintf(cmd, sizeof(cmd), fmt, ap);
va_end(ap);
if (num < 0 || num >= (int)sizeof(cmd))
return -1;
int ret = system(cmd);
if (ret < 0)
return -1;
return (WIFEXITED(ret) && WEXITSTATUS(ret) == 0) ? 0 : -1;
}
qt 相关的经验总结:
1.信号处理:
signal(SIGTERM, handler);
void handler(int signum)
{
if(signum == SIGTERM)
{
qDebug()<<“sigterm”;
// st.close_action();
exit(0);
}
else if(signum == SIGUSR1)
{
qDebug(“\nhwnd start######”);
std::map<int, MainWindow*>::iterator iter = win_map.begin();
for(;iter != win_map.end(); ++iter)
{
qDebug()<first;
}
qDebug(“hwnd end######”);
}
}
2. 设置最后一个窗体关闭时,程序不退出
app.setQuitOnLastWindowClosed(false);
3.透明窗口鼠标穿透,使用xlib的东西
setAttribute(Qt::WA_TransparentForMouseEvents, true);
setWindowFlags(Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground, true);
XShapeCombineRectangles(QX11Info::display(), this->winId(), ShapeInput, 0, 0, NULL, 0, ShapeSet, YXBanded);
git技巧
- git show HEAD 显示提交的具体代码
- git commit --amend 修改上一次提交的内容,(已经提交未push,发现还有个东西没改就可以用这个)
比如在fun1.cpp的第45行设置断点:
break fun1.cpp:45
然后 p 变量名查看当前变量
GDB动态打印命令dprintf来实现print消息的输出,
dprintf原理
dprintf命令会设置一个特殊的断点,这可以通过info break查看,dprintf设置了类型为dprintf的特殊断点,当程序执行到该断点
时,GDB将按照template和expression打印消息,打印完成后继续执行程序。这个过程非常短暂(和仿真器的速度有关),人是感觉
不出程序停顿的,所以看起来就跟是目标程序在打印消息一样。
dprintf用法
在指定行打印
dprintf perf_msgr_client.cc:133,“Test send i = %d,ops = %d,inflight = %d\n”,i,ops,inflight
在指定函数打印
dprintf perf_msgr_client.cc:ready,“In fun ready:c= %d,jobs=%d\n”,c,jobs
gdb 遇到的一个异常退出的问题
参考链接
现象是:起spice 的时候,发现spice 异常退出了,但是很奇怪没有core 文件产生,于是用gdb attach看了一下,
发现gdb 报错:[Inferior 1 (process 27641) exited with code 0177]
查看当前堆栈,什么信息都没有?
就很奇怪,然后上网搜了,发现最后实际是因为动态库的原因,
很蠢, 建立了软连接 abc.1 -> abc.1.1.0 然后因为之前调试 将 abc1.1.0 改名为abc1.1.0_bak 然后copy了一个新的abc.1.1.0 我以为 软连接就会指向这个新的动态库。。。
遇到的一个有意思的题(内存分布问题)
class A
{
public:
int y = 5;
int x = 1;
void exec()
{
x = 2;
}
};
class B
{
public:
int x = 3;
int y = 6;
void exec()
{
x = 10;
}
};
A a;
B* bp = (B*)&a;
B b = *bp;
a.x = ? bp->x = ? b.x = ?
bp->exec();
a.x = ? bp->x = ? b.x = ?
ans is :
只能说自己对于C++ 的内存分配记忆还不是很深刻
第一行的a.x = 1 没问题,
bp->x 为什么等于5?
原因很简单,看一下内存里分布,A 类 前四个字节表示y,后四个字节才表示x,但是这时候强制类型转换了,bp指针是B 类的,而B类中前四个字节表示x,后四个字节才表示y,因此bp->x 打印A 类前四个字节,也就是5;
b.x 同样拷贝构造之后x=a.y=5;