Intelligence without ambition is a bird without wings.

2015-09-01
linux-环境变量

相关配置文件加载顺序

1
2
/etc/enviroment => /etc/profile => /etc/bash.bashrc => /etc/profile => /etc/profile.d/*.sh
=> ~/.profile(~/.bash_profile, ~/.bash_login) => ~/.bashrc => ~/.bash_aliases => /etc/bash_completion

说明

  • /etc/enviroment

    在系统一些核心组件加载完成后最先调用,系统级别的公共环境变量

  • /etc/profile

    在login shell时读取, 相当于是应用级的公共环境变量

  • ~/.profile

    在shell被打开时, 次于/etc/profile执行, 相当于是应用级的用户环境变量

阅读此文

2015-08-26
gcc-调试编译

  • 打印编译详细过程

    -v

阅读此文

2015-08-26
gcc-链接库顺序

说明

在gcc编译时,链接库的指定顺序会影响编译行为!

gcc手册说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-l library
Search the library named library when linking. (The second alternative with the library as a separate argument is only for POSIX compliance and is not
recommended.)

It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are
specified. Thus, foo.o -lz bar.o searches library z after file foo.o but before bar.o. If bar.o refers to functions in z, those functions may not be
loaded.

The linker searches a standard list of directories for the library, which is actually a file named liblibrary.a. The linker then uses this file as if
it had been specified precisely by name.

The directories searched include several standard system directories plus any that you specify with -L.

Normally the files found this way are library files---archive files whose members are object files. The linker handles an archive file by scanning
through it for members which define symbols that have so far been referenced but not defined. But if the file that is found is an ordinary object file,
it is linked in the usual fashion. The only difference between using an -l option and specifying a file name is that -l surrounds library with lib and
.a and searches several directories.

理解:

假设C依赖库A,B,库B依赖于库A,则链接的时候要写为:

gcc -o C -lB -lA

若写成:

gcc -o C -lA -lB

链接时,符号寻找过程

  1. 根据库路径列表,依次找到需要链接的库

    • 若一个库在该路径列表中存在多个,则使用第一个找到的
  2. 从左向右,依次找寻符号定义

    • gcc -o C -lB -lA,符号搜寻过程是C=>B, B=>A

结论!

在项目开发过层中尽量让lib是垂直关系,避免循环依赖,越是底层的库,越是往后面写

g++ ...  obj($?) -l(上层逻辑lib) -l(中间封装lib) -l(基础lib) -l(系统lib) -o $@

参考

  1. 折腾gcc/g++链接时.o文件及库的顺序问题
阅读此文

2015-08-26
mysql-C开发

编译器参数

mysql_config --cflags --libs
阅读此文

2015-08-26
arch-修改键盘映射

阅读此文

2015-08-17
mysql-mysql_use_result-VS-mysql_store_result

mysql_use_result

保留了如何从服务器取结果集

优势

  • 客户端占用内存小

劣势

  • 不能随机访问结果行

  • 必须访问完,才能获取行数

  • 客户端对结果处理必须得快,否则对服务端造成压力

  • 必须从服务端获取所有结果,即使已经找到需要的行

mysql_store_result

将sql执行结果全部获取到客户端

优势

  • 能直接获取结果行数

  • 能随机访问结果行

劣势

  • 客户端占用内存大,可能内存溢出

共同点

  • 都需要调用mysql_free_result释放内存

参考

  1. mysql-manual.23.8.6
阅读此文

2015-08-17
条件变量

为什么需要条件变量

  • mutex只能保证互斥地操作共享资源,不能及时通知其他线程某一条件已经满足
阅读此文

2015-08-17
虚假唤醒

描述

在使用条件变量时,有可能pthread_cond_wait返回时,条件并不满足

原因

  • 在多核CPU上无法完全实现条件操作语义

如何避免

1
2
3
4
5
pthread_mutex_lock(&lock);
while (condition_is_false) {
pthread_cond_wait(&cond, &lock);
}
pthread_mutex_unlock(&lock);

参考

  1. http://www.fenesky.com/blog/2014/06/22/cond-spurious-wakeup.html
阅读此文

2015-08-15
pthread-主线程等待线程组结束

1
2
3
4
5
6
7
8
9
10
11
12
for (int i = 0; i < THREAD_NUM; ++i) {
if (pthread_create(&tid[i], NULL, counter, (void *)&i) != 0) {
perror("pthread_create error");
exit(1);
}
}
for (int i = 0; i < THREAD_NUM; ++i) {
if (pthread_join(tid[i], NULL) != 0) {
perror("pthread_join error");
exit(1);
}
}

参考

  1. http://stackoverflow.com/questions/11624545/how-to-make-main-thread-wait-for-all-child-threads-finish
阅读此文

2015-08-15
多线程同步

要求

  1. 子线程升序打印线程编号(主线程传进去的)

  2. 子线程升序打印全局变量

未同步前

代码

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
#define THREAD_NUM 10   // 线程个数
int count = 0; // 共享资源


void *counter(void *arg)
{

int num = *(int *)(arg);

sleep(1); // 处理其他无需同步的操作
count++;
cout << "线程编号: " << num << ":" << count << endl;

return (void*)0;
}


int main(int argc, char *argv[])
{

pthread_t tid[THREAD_NUM];

for (int i = 0; i < THREAD_NUM; ++i) {
if (pthread_create(&tid[i], NULL, counter, (void *)&i) != 0) {
perror("pthread_create error");
exit(1);
}
}
sleep(5);

return 0;
}

结果

原因及解决

  • 创建子线程后,线程调度顺序不可预测(可能主线程先运行,也可能子线程先运行)

    解决: 同步主线程和子线程的运行顺序,使子线程运行后,主线程在运行

  • 子线程对共享资源操作未同步

    解决: 对共享资源采取同步手段(互斥锁)

同步后

代码

阅读此文