用 process_vm_readv() 实现多进程内存队列

一,问题背景

多进程之间需要传输大量数据的时候,比如多进程 RPC 框架的进程之间通信,常用共享内存队列。

但是共享内存队列难免会有 入队+出队 2次 memcpy 。

而且要变长共享内存队列,如果支持多生产者进程+多消费者进程 ,就要处理线程安全方面的问题, 比较麻烦。

process_vm_readv() , process_vm_writev() 是 Linux 3.2 新增的 syscall,用于在多个进程的地址空间之间,高效传输大块数据。

https://www.man7.org/linux/man-pages/man2/process_vm_readv.2.html

https://github.com/open-mpi/ompi/blob/master/opal/mca/btl/sm/btl_sm_get.c#L96

在此, 我提个设想,可以用 process_vm_readv 实现一个多进程内存队列,相比之下,优势是:

  1. 在处理 多线程/多进程 并发时,更简单
  2. 省掉一次 memcpy。

下面 demo 代码演示了这个思路。 为了方便,直接用 posix mq 来传输 iovec 数组,也没有考虑多路复用。 真实项目可能需要 eventfd 之内的机制来做 notify。

实测了下,3个进程加起来有 5.5 GB/秒 的速度。

构造最短程序打印自身的 MD5

一,介绍

比赛题目很简单:构造一个程序,在 stdout 上打印出自身的 MD5,程序越短越好。按最终程序文件大小字节数排名,文件越小,排名越靠前。 只能使用 ld-linux-x86-64.so, libc.so, libdl.so, libgcc_s.so, libm.so, libstdc++.so 。 禁止了 socket, shmget, fork, execvc 等 syscall 。

汇编高手如云,本人只做到 752 字节,只拿到 27 名。 但忙活好几天,学到不少东西,也有苦劳,还是值得记录一下。

基本是纯 C 实现,没有动用汇编。

基于 ElasticSearch 开发垂直搜索系统

一,背景介绍

ElasticSearch 是由 Lucene 包装上分布式复制一致性算法等附加功能,构成的开源搜索引擎系统。

近两年在业界热度大增,主要有 3 种应用场景:

  1. 全文搜索引擎
  2. NOSQL 数据库
  3. 日志分析数据库 ELK

很多垂直领域搜索需求,都可以基于 ElasticSearch 来设计架构。

ElasticSearch 能大幅度提升相关业务的迭代开发速度,实现类似 sql 数据库增删改查一样的快速开发。 并在相对高 qps 的在线业务中,保证毫秒级的延迟,提供极高的可用性和稳定性。

经过持续的研读官方文档,调研业界经验,并在实践中应用反思后,总结出一套架构方案。供参考,欢迎意见建议。

怎样让 C++ 中 throw exception 产生的 coredump 带上栈

1. 问题

一个 C++ 程序,如果 throw 了 exception ,但是又没有 catch,那么一般会产生 coredump, 问题是,在 gcc 4.x 版本产生的 coredump 文件中,没有 throw 时候的堆栈信息,导致不知道是哪里 throw 的,没法查问题。

原因是 gcc 4.x 的 /libstdc++-v3/src/c++11/thread.cc:92 里面有个 catch(…),所以 stack unwind 了,就没了 throw 时候的 stack 。

1
2
3
4
5
6
7
void * execute_native_thread_routine(){
    try {
     ...   
    }catch(...){
        std::terminate();
    }
}

https://abcdabcd987.com/libstdc++-bug/

一个解决办法是可以升级 GCC 7 ,或者可以用更简单的办法:

用 abstract unix socket 实现进程单实例运行

一,问题背景

很多时候,我们需要确保进程只有一个实例运行

有几种方法:

http://stackoverflow.com/questions/2964391/preventing-multiple-process-instances-on-linux

http://stackoverflow.com/questions/5339200/how-to-create-a-single-instance-application-in-c-or-c

https://github.com/qtproject/qt-solutions/tree/master/qtsingleapplication/src

比较常规的做法,是对一个文件加文件锁 flock,比如对 pid 文件 flock( LOCK_EX|LOCK_NB )

但是这种方法有些弊端:

  1. 如果文件被 mv 或者 rm,是会被绕过的。
  2. 如果磁盘故障比如磁盘满,目录没有写权限,会失败。

二,abstract namespace unix socket

http://linux.die.net/man/7/unix

unix socket 有3种:

  1. 基于文件的
  2. socketpair 创建的,匿名的
  3. abstract namespace 的,Linux特有

Linux 下, AF_UNIX socket 支持一种特殊的 abstract namespace unix socket 。

相比 普通的基于文件系统的 unix socket,abstract namespace unix socket :

  1. 没有磁盘文件
  2. 进程挂了以后自动删除,无残留文件
  3. 无需担心与 文件系统上的文件冲突,不需要关心文件系统上的绝对路径是否存在的问题