上一篇简要介绍了守护进程,现在就来实践一下,写一个自动关机的小程序。该程序可以守护进程的方式运行,当用户在一定时间(比如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之类的文件。
不足之处在于,无法对全屏模式进行判断,即是说,如果你全屏看一部较长的电影,可能会被关机……
如果你有好的方法来实现本文的功能,还请不吝赐教!
Archive for ‘Unix/Linux’ Category
守护进程(daemon process,又称精灵进程),是一种运行在后台,不需要与用户进行交互的程序,其特性与Windows中的服务类似。Linux/Unix系统中运行着很多这样的进程,且很多此类进程的进程名都采用named的形式,比如httpd, vsftpd, inetd等。但这只是一种命名惯例,你完全可以采用其它的命名形式。
守护进程的特性
守护进程有种种特性,使之成为守护进程。
运行周期较长。守护进程通常在系统启动时由/etc/rc*.d中的启动脚本或者用户在终端手动启动,在系统结束时停止或由用户手动停止。不像普通进程那样在用户退出终端后就被停止,守护进程会一直运行(下面会看到守护进程在启动后会脱离执行它的终端)。
脱离其运行环境。守护进程没有控制终端。进程在创建时(fork)会继承父进程的PCB(进程控制块),因此会同时拥有父进程的许多资源和关系,比如打开的文件描述符、socket、环境变量、控制终端、进程组、登录会话等。而守护进程需要关闭这些资源、脱离这些关系。
chmod命令介绍
下面介绍如何使用chmod命令来设定和修改文件的权限位。
首先,chmod命令本身的执行也有限制,普通用户只能修改自己的文件的权限位,超级用户可以使用chmod修改任意用户任意文件的权限。使用chmod的方法为chmod [option] mode file. 常用的选项就是-R,用来对整个目录及其子目录中的文件进行模式(权限)修改。mode可以由两种方式指定,一种是由字母表达式表示的相对修改方式,一种是以4位8进制表示的绝对方式。
第一种方式:chmod [ugoa][+-=][rwxst] file. u指代user,g指代group,o指代other,a指代all。+-=分别执行指代增加、减少、设定相应权限(由后面的参数指定)。rwxst分别指代读、写、执行、set-user-id/set-group-id、sticky-bit粘滞位。整体上理解,就是对哪类用户(ugoa,为a时可省略)执行哪些权限(rwxst)的什么修改(+-=)。示例:
1 2 3 4 5 6 7 8 9 10 11 12 | $ chmod u-x a.out $ ll a.out -rw-r-xr-x 1 dutor dutor 7.1K 2010-08-08 13:33 a.out $ chmod +t a.out $ ll a.out -rw-r-xr-t 1 dutor dutor 7.1K 2010-08-08 13:33 a.out $ chmod g=rs a.out $ ll a.out -rw-r-Sr-t 1 dutor dutor 7.1K 2010-08-08 13:33 a.out $ chmod a+x a.out $ ll a.out -rwxr-sr-t 1 dutor dutor 7.1K 2010-08-08 13:33 a.out |
配置inputrc
我们这里需要的是一种叫做菜单式补全(menu-complete)的功能。通常,默认情况下,这个选项是没有被配置的。为了配置这项功能,并为之进行快捷键绑定,我们需要修改inputrc配置文件,这个文件中保存了Readline的一些键绑定和其它诸如编辑模式的配置选项。像许多其它配置文件一样,inputrc有系统级的配置选项/etc/inputrc和用户级的点文件~/.inputrc。建议建立自己的点文件,而不是直接编辑系统级文件,当然如果整个系统只是你一个人在用的话,你也可以在/etc/inputrc上面直接编辑。但使用点文件的另一个好处告诉你,它是属于你自己的,即使在另外一个不同的发行版上,点文件通常也是可以直接使用的。这可以减轻你在不同系统上的不适。
好了,打开或者建立你的.inputrc,写下,下面两行:
1 2 | "\C-j": menu-complete "\C-k": menu-complete-backward |
动态链接库
动态库和静态库相似,也是各个目标文件的集合。但相比静态链接的程序,动态链接可执行程序要小得多:这类程序运行时需要外部共享 函数库的支持,因此好像并不完整。除了程序体小之外,动态链接允许程序包指定必须的库,而不必将库装入程序包内。动态链接技术还允许多个运行中的程序共享一个库,这样就不会出现同一代码的多份拷贝共占内存的情况了。由于这些原因,当前多数程序采用动态链接技术。
在Linux中的扩展名通常为.so。但在链接时,并不会被链接到可执行文件中,而是在执行时(需要时)由操作系统的动态加载模块动态地加载到内存,并链接到可执行文件地址空间的相应位置。
动态链接库的创建也分为编译和”归档”两个阶段,但不同的是在这两个阶段需要使用一些不同的命令选项。首先,需要将源文件编译成一种成为位置无关码(PIC: Position Independent Code)的目标文件,这种代码可以被加入到内存的任何位置却不需要加载器对其进行重定位,关于这种格式可以参考《链接器与加载器》和《程序员的自我修养–链接装载与库》中较为详尽的描述。接下来需要将这些位置无关码“归档”为.so文件。整个过程只需一个工具即可,即gcc。还是上面的源文件,执行以下命令:
1 2 | $ cc -c -fpic plus.c sub.c $ cc -shared -o libmath.so *.o |
find命令可以按照指定的规则对硬盘上的文件进行查找,且可以跨越不同的文件系统。find命令的使用方法:
1 | find fold [option] |
下面按照不同的选项介绍find命令。
find -name
-name是最常用的选项,它指定了需要查找的文件名的模式,模式中可以使用通配符和简单的正则表达式。下面的命令查找Wdir目录下的.cpp文件:
1 2 3 4 5 6 7 8 9 10 11 | dutor@dutor-desktop:~$ find Wdir -name "*.cpp" Wdir/Cpp/Pthread/main.cpp Wdir/Cpp/STL/sort_list.cpp Wdir/Cpp/STL/Heap.cpp Wdir/Cpp/STL/operator.cpp Wdir/Cpp/STL/bind2nd/main.cpp Wdir/Cpp/STL/Kth-Max.cpp Wdir/Cpp/STL/priority_queue.cpp Wdir/Cpp/ACM/Huffman/main.cpp Wdir/Cpp/ACM/Bellman-Ford/main.cpp ...... |
需要注意的是,如果搜索目录以相对路径形式指定,则搜索结果也以相对路径形式给出;否则,搜索结果以绝对路径形式给出。
Linux/Unix中有两种链接,硬链接和软链接,均由ln命令来创建。
软链接
软链接使用ln命令的-s选项创建:
1 | ln -s source target #创建source文件的软链接target |
软链接类似于Windows中的快捷方式,内部保存的是源文件的路径,路径可以是相对路径,也可以是绝对路径:
1 2 3 4 5 6 | dutor@dutor-desktop:~$ ln -s gvim.tgz gvim dutor@dutor-desktop:~$ ln -s /home/dutor/gvim.tgz gvim2 dutor@dutor-desktop:~$ ll gvim* # alias ll='ls -l' lrwxrwxrwx 1 dutor dutor 8 2010-07-01 20:32 gvim -> gvim.tgz lrwxrwxrwx 1 dutor dutor 20 2010-07-01 20:33 gvim2 -> /home/dutor/gvim.tgz -rw-r--r-- 1 dutor dutor 8.5M 2010-06-29 23:06 gvim.tgz |
软链接应用十分广泛。
ls == list,根据不同的选项,列举指定目录或文件的相关信息,是Unix/Linux下最常用的命令之一,cd到某一目录下后执行的第一个命令。
ls
不带参数的ls列举当前目录下有哪些文件和目录,ls Folder列举Folder目录中的文件和子目录,ls File显示File文件的信息(默认为文件名)。
1 2 3 4 5 6 7 8 9 | dutor@dutor-desktop:~$ cd Wdir/ /home/dutor/Wdir dutor@dutor-desktop:~/Wdir$ ls APUE ASM Cpp LaTeX PHP Python QT Shell dutor@dutor-desktop:~/Wdir$ ls Cpp/ ACM main main.cpp Makefile Pthread symtab tags test.s Curses main.c main.s Playaround STL SystemProgram test.c TutManual dutor@dutor-desktop:~/Wdir$ ls Cpp/Makefile Cpp/Makefile |
上一篇[命令技巧]mkcd中,mkcd函数里面使用到了mkdir的-p选项。mkdir的-p选项允许你一次性创建多层次的目录,而不是一次只创建单独的目录。例如,我们要在当前目录创建目录Projects/a/src,使用命令
1 | mkdir -p Project/a/src |
而不是
1 2 3 4 5 | mkdir Project cd Project mkdir a cd a mkdir src |
介绍一个新命令,保准你从未听说过,但它实现的操作你应该一直都在使用,这个命令就是mkcd。其实它不是一个命令,而是一个shell函数:
1 2 3 4 5 6 7 8 9 10 11 | # mkcd: mkdir, then cd mkcd() { if [ $# = "1" ] then mkdir -p "$1" cd "$1" else echo "Usage: mkcd folder" fi } |
很简单,相信你一看就知道它能做什么了。