想必您经常使用复制粘贴功能吧,如果你在桌面环境下工作的话。那么您对Ctrl + C与Ctrl + V一定很熟悉了,您可能还经常使用中指按下鼠标的中键来快捷的粘贴。在X中,此两种粘贴方式是有区别的。Ctrl + V之前要有选中和相应的Ctrl + C,而中键之前只需要选中即可,前者使用的是剪切板(Clipboard),后者使用的是选中(Primary Selection)。关于两者细微的区别见这里
  下面要介绍的是一个能够在命令行访问剪切板(或者Selection,下面以“剪切板”概而论之)的工具。你可能知道,所谓剪切板以及复制粘贴这些功能都是X提供的,而不是Linux内核本身。因此,在命令终端访问剪切板就显得不那么简单,不那么显而易见了。

1
2
3
4
#! /bin/bash
content=`xclip -o`
echo $content >>/.wordump.txt
exit 0
Tags: .

  xbindkeys是一个可以全局按键绑定的程序,使用它,你可以方便用自定义的快捷键序列,来启动常用的程序。而且,xbindkeys独立与桌面环境,无论是gnome, KDE还是xfce,都可以使用同一个xbindkeys配置。、
  xbindkeys最新版本是v1.8.3,而ubuntu10.04的源中还是v1.8.2,较旧的版本在修改配置文件后“立即生效”上有bug,最新版本已经修复。
  安装好xbindkeys后,使用下面命令生成默认的配置文件,

1
$ xbindkeys --default > ~/.xbindkeysrc

  生成的配置文件的格式大致是这样的:

Tags: .

  我编写程序至今有35年了,我做了很多关于程序执行速度方面优化的工(一个示例),我也看过其它人做的优化。我发现有两个最基本的优化技术总是被人所忽略。
  注意,这两个技术并不是避免时机不成熟的优化。并不是把冒泡排序变成快速排序(算法优化)。也不是语言或是编译器的优化。也不是把 i*4写成i<<2的优化。

  这两个技术是:

  • 使用 一个profiler。
  • 查看程序执行时的汇编码。
Tags: ,.

  在很多C/C++头文件中,你可能会经常看到使用extern “C”{}包含起来的代码。这种语法的存在是为了使C和C++代码能够兼容。兼容?C++对C本来不就是兼容的吗?确实,在语法层面,C++支持几乎所有C语法。但这里的兼容是目标文件或者库级别的兼容,包括两种情况下的兼容。一种是,在C++代码中调用已经存在的C代码写成的库;另一种是,使用C编写代码,而希望这些代码能够使C++可以调用。
  若想继续讨论extern “C”,就不得不提name mangling。
  我们知道,相比C,C++支持函数重载,支持命名空间,支持类以及成员函数。函数重载允许我们声明名字相同参数不同的函数,命名空间(namespace)和类为名字(或者说符号)划分了不同的域使得我们可以在不同域中使用完全相同的名字。而为了实现这种特性,C++就使用了name mangling。即是说,C++编译器在编译C++文件时,把每一个函数名“打乱”成与函数所在域、参数类型、调用约定相关的另外一个名字(因为汇编级别的代码中,所有符号都在同一个域)。由于C中并不存在这些特性,所以通常C编译器并不对符号进行mangling。

Tags: ,.

  那么,C/C++中,哪些地方是顺序点呢?

  • 每个表达式的结束处;
  • 函数调用中,在所有参数求值完成后,函数体开始执行前有一个顺序点,而参数间的逗号处则没有顺序点。所以f(++i, ++i)的行为也是未定义的;
  • 逻辑运算符&&、||还有条件运算符?:的第一个参数末尾处有一个顺序点;
  • 逗号表达式中每一个逗号处有一个顺序点。因此x = (++i, ++i)是有确定行为的;
  • 在每一个完整的变量声明处有一个顺序点,例如int i, j;中逗号和分号处分别有一个顺序点;
  • for循环控制条件中的两个分号处各有一个顺序点。

  那么,现在,这个程序有问题吗?

1
2
3
4
5
6
7
8
9
int
main()
{
    int m = 1, n = 0;
    printf("%d, %d\n", m, n);
    m ^= n ^= m ^= n;
    printf("%d, %d\n", m, n);
    return 0;
}
Tags: ,,.

  由于守护进程在后台运行,为系统或用户提供某种服务,因此通常只需要一个运行实例就可以了,而且在大部分情况下只能有一个实例在运行。例如cron进程,若有多个实例在运行,那么各个实例都会根据crontab执行一份用户指定的任务,岂不是乱了套了?还有其他很多守护进程是设备相关的,而这些设备有很可能是非共享的,所以这样的守护进程也不能运行多个。
  文件锁和记录锁机制是一种实现守护进程单例运行的方法。如果每一个守护进程创建一个文件,并且在整个文件上加上一把锁,那就只允许创建一把这样的写锁,所以在此之后试图再创建一把这样的写锁就会失败,以此向后续守护进程的副本指明已经存在一个正在运行的副本了。守护进程终止时,这把锁将被自动删除。

1
2
3
4
5
6
7
8
9
10
int
lockfile(int fd) //~ try to lock the file, affecting errno when it fails.
{
    struct flock fk;
    fk.l_type = F_WRLCK;
    fk.l_start = 0;
    fk.l_whence = SEEK_SET;
    fk.l_len = 0;
    return (fcntl(fd, F_SETLK, &fk));
}
Tags: .

See this,

1
2
3
4
5
6
7
8
9
10
int
main()
{
    int x = -1,
        y = -1,
        z = 0;
    printf("%d\n", ++x || ++y && ++z);
    printf("%d, %d, %d\n", x, y, z);
    return 0;
}

  别说我无聊,没人(正常人)会写出这样的式子,但有些细节知道总比不知道的好。
  &&比||优先级高。
  但优先级和求值顺序是两码事。
  ||和&&的求值顺序都是从左到右。其它运算符只有三目运算和逗号运算符有特定顺序,而+ – * /等的操作数均无特定的求值顺序,即f(x) + g(x++)中那个函数首先被调用是未定义的。顺便提一句,函数的参数的求值顺序与其入栈顺序也是无关的,所以f(i++, i++, i++)的行为也是未知的。

Tags: .

  上一篇简要介绍了守护进程,现在就来实践一下,写一个自动关机的小程序。该程序可以守护进程的方式运行,当用户在一定时间(比如30分钟)没有鼠标和键盘操作后就会自动关机。
  这个程序利用了上篇文章中实现的daemonize函数,为程序创建了守护进程所需要的运行环境。
  由于需要同时监听鼠标和键盘操作,所以需要采用多线程的方式来实现。其中两个线程分别监视鼠标和键盘,一旦检测到相应动作(鼠标点击和移动、击键等),全局时间戳stamp(time_t)就会被设成当前时间。主线程每隔一定时间(比如1秒)检查stamp,若当前时间值(time(NULL))比stamp大30*60,则执行停机操作(使用system函数执行init 0命令,或者使用reboot函数)。
  需要说明的是,共享变量stamp需要互斥地访问。另外,对鼠标事件的监听是借助于对设备文件/dev/input/mice的读取(阻塞方式),键盘的监听借助于对/dev/input/event3的阻塞读取,但我猜想在不同机器上可能会是其它诸如event0,event5之类的文件。
  不足之处在于,无法对全屏模式进行判断,即是说,如果你全屏看一部较长的电影,可能会被关机……
  如果你有好的方法来实现本文的功能,还请不吝赐教!

Tags: ,.

  守护进程(daemon process,又称精灵进程),是一种运行在后台,不需要与用户进行交互的程序,其特性与Windows中的服务类似。Linux/Unix系统中运行着很多这样的进程,且很多此类进程的进程名都采用named的形式,比如httpd, vsftpd, inetd等。但这只是一种命名惯例,你完全可以采用其它的命名形式。

守护进程的特性

  守护进程有种种特性,使之成为守护进程。
  运行周期较长。守护进程通常在系统启动时由/etc/rc*.d中的启动脚本或者用户在终端手动启动,在系统结束时停止或由用户手动停止。不像普通进程那样在用户退出终端后就被停止,守护进程会一直运行(下面会看到守护进程在启动后会脱离执行它的终端)。
  脱离其运行环境。守护进程没有控制终端。进程在创建时(fork)会继承父进程的PCB(进程控制块),因此会同时拥有父进程的许多资源和关系,比如打开的文件描述符、socket、环境变量、控制终端、进程组、登录会话等。而守护进程需要关闭这些资源、脱离这些关系。

Tags: ,.

  正常情况下,在终端编译执行该多线程程序,首先打印n(0),5秒后再次打印n(1),然后该进程正常退出。
  但,如果使用gcc编译此程序时,使用优化选项(比如-O1),再执行此程序。首先打印n(0),5秒后再次打印n(1),然后呢,然后就死循环啦!
  为什么呢?看一看汇编代码就知道了,使用gcc -O1 -S命令编译第一段代码,得到的汇编码:

1
2
3
4
5
6
7
main:
    movl    n(%rip), %eax #从内存中取n值至寄存器eax
.L3:
    testl   %eax, %eax # 与测试eax
    je  .L3 # eax0时跳转至标号L3处
    movl    $0, %eax
    ret

  真相大白了吧,那该怎么办?对,volatile,参看这里

Tags: ,.
Page 5 of 3112345678910...2030...Last »