ZM改进遇到的exec函数族问题

最近在改进ZM视频存储过程中,在修改底层C程序中,想加一句脚本去执行(代码如下),发现执行过脚本后程序却不能继续执行下去。

char *I = [];

sprint(I, %d, id);

execl(“/usr/local/bin/zmvideo.pl”,”zmvideo.pl”,”-e”,i,”-f”,”avi”,”-o”,NULL);

……;

几次尝试后,直觉告诉我们,可能是execl函数占用了当前进程的资源,导致函数不能继续执行。

上网一查,果然是,“当进程调用一种exec函数时,该进程完全由新程序代换,而新程序则从其main函数开始执行。因为调用exec并不创建新进程,所以前后的进程ID并未改变。exec只是用另一个新程序替换了当前进程的正文、数据、堆和栈段”。

那么就修改了代码,创建一个子进程,问题就解决了:

 

原来是exec函数族都有这样一个特性,他把当前进程映像替换成新的程序文件,而且该程序通常main函数开始执行!

用fork函数创建子进程后,子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程完全由新程序代换,而新程序则从其 main函数开始执行。因为调用exec并不创建新进程,所以前后的进程ID并未改变。exec只是用另一个新程序替换了当前进程的正文、数据、堆和栈段。有六种不同的exec函数可供使用,它们常常被统称为exec函数。这些exec函数都是UNIX进程控制原语。用fork可以创建新进程,用exec可以执行新的程序。exit函数和两个wait函数处理终止和等待终止。这些是我们需要的基本的进程控制原语

说是exec系统调用,实际上在Linux中,并不存在一个exec()的函数形式,exec指的是一组函数,一共有6个,分别是:

 

 

其中只有execve是真正意义上的系统调用,其它都是在此基础上经过包装的库函数

下面详细介绍一下exec函数族。exec函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内容,换句话说,就是在调用进程内部执行一个可执行文件。这里的可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件,如果不是可以执行的文件,那么就解释成为一个shell文件,sh **执行!

上面6条函数看起来似乎很复杂,但实际上无论是作用还是用法都非常相似,只有很微小的差别。

参数argc指出了运行该程序时命令行参数的个数,数组argv存放了所有的命令行参数,数组envp存放了所有的环境变量环境变量指的是一组值,从用户登录后就一直存在,很多应用程序需要依靠它来确定系统的一些细节,我们最常见的环境变量是PATH,它指出了应到哪里去搜索应用程序,如 /bin;HOME也是比较常见的环境变量,它指出了我们在系统中的个人目录。环境变量一般以字符串”XXX=xxx”的形式存在,XXX表示变量名,xxx表示变量的值。

值得一提的是,argv数组和envp数组存放的都是指向字符串的指针,这两个数组都以一个NULL元素表示数组的结尾。

现在来看一下exec函数族,先把注意力集中在execve上:

int execve(const char *path, char *const argv[], char *const envp[]);

execve第1个参数path是被执行应用程序的完整路径,第2个参数argv就是传给被执行应用程序的命令行参数,第3个参数envp是传给被执行应用程序的环境变量

在这里有点要注意,不管是arg0,还是argv[0]都必须是程序的可执行文件的名字,比如

execl(“/bin/echo”, “echo”, “executed by execl”, NULL)中的echo;

execl(“/bin/ls”, “ls”, “/azuo”, “-la”, (char *)0 )中的ls;

execlp(“echo”, “echo”, “executed by execlp”, NULL)中的echo;

留 心看一下这6个函数还可以发现,前3个函数都是以execl开头的,后3个都是以execv开头的,它们的区别在 于,execv开头的函数是以”char *argv[]”这样的形式传递命令行参数,而execl开头的函数采用了我们更容易习惯的方式,把参数一个一个列出来,然后以一个NULL表示结束。这 里的NULL的作用和argv数组里的NULL作用是一样的。

这里建议使用 (char *)0 代替NULL。

在全部6个函数中,只有execle和execve使用了char *envp[]传递环境变量,其它的4个函数都没有这个参数,这并不意味着它们不传递环境变量,这4个函数将把默认的环境变量不做任何修改地传给被执行的应用程序。而execle和execve会用指定的环境变量去替代默认的那些。

还 有2个以p结尾的函数execlp和execvp,咋看起来,它们和execl与execv的差别很小,事实也确 是如此,除execlp和 execvp之外的4个函数都要求,它们的第1个参数path必须是一个完整的路径,如”/bin/ls”;而execlp和execvp的第1个参数 file可以简单到仅仅是一个文件名,如 “ls”,这两个函数可以自动到环境变量PATH制定的目录里去寻找。

ZoneMinder改进前瞻

接触ZM也有几个月有余,对其功能也都有所了解,深感ZM功能之强大。近半月实验室又采购了四台海康威视网络摄像头,又了解了业界领先厂商产品的设计之成熟,强大的功能加上良好的用户体验指明了我们的研究方向。对比ZM与现在的主流产品,ZM还是有很好的功能基础,再加上代码开源提供了修改平台,使日后的改进、增加功能成为可能。经过对比,现总结出ZM亟待改进的三个方面:存储方式、事件检索、抓图功能。

  •  存储方式

可能是ZM设计者的初衷是在家中安装监控摄像头,并没有考虑到大规模应用带来的存储空间的瓶颈,采用的是保存每一帧图片的形式来保存视频数据的。这样一来,近似于没有采用压缩编码,没有去除图像之间的冗余,造成了存储空间的浪费。针对这个问题,目前计划采用两步走的策略,来对ZM存储方式进行改进。

  1. 第一步:文件级存储

ZM本身具有能将图片合成视频文件的功能,经过实验,导出的视频文件(以avi格式)的大小为图片大小总和的7%。首先利用这一功能,将图片转成视频文件存储作为第一步,设定5分钟、10分钟或半小时生成一次视频文件,可大大减小存储空间使用。

  1. 第二步:视频流存储

文件级存储满足了节省空间的需求,但是在用户回放时不能做到秒级回放,必须要等到视频文件生成后才能回放。视频流存储即视频的数据块存储,很好地解决了这一问题,它是将视频数据以视频流的方式持续写入磁盘,由于采用的数据块的形式,可以实现事件的秒级回放。

  • 事件检索

目前ZM对于事件的检索功能,仅限于在事件过滤器中若干条件的组合可以过滤出满足条件的事件,各条件采用与、或的关系组合,用户操作起来比较繁琐。因此有必要提取出事件搜索功能,目前计划事件检索模块可以实现用户针对特定摄像头和特定时间区间的事件搜索功能。

  • 抓图功能

通过对目前市场主流产品的调研,视频抓图以成为监控系统一项重要的功能,用户可在实时查看、回放过程中随时抓取关键图片,作为时候取证的有力保证。在ZM中,计划也增加抓图功能,用户在观看过程中通过点击即可抓取一帧或几帧的关键图片,并单独保存,同时将图片检索也集成到事件检索中。

关于ZoneMinder的改进暂且先列出如上几点,这几天看了ZM的源码,认为改进ZM必须要首先掌握整个代码的结构,深入理解各部分功能的实现,深感路漫漫其修远兮,但吾将上下而求索。

CentOS6.3下NFS安装遇到的问题与解决

1.安装遇到的问题

[root@localhost NFS]# rpm -ivh nfs-utils-lib-1.0.8-7.6.el5.x86_64.rpm
warning: nfs-utils-lib-1.0.8-7.6.el5.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ID e8562897: NOKEY
error: Failed dependencies:
libldap-2.3.so.0()(64bit) is needed by nfs-utils-lib-1.0.8-7.6.el5.x86_64

 

[root@localhost NFS]# rpm -ivh nfs-utils-lib-devel-1.0.8-7.6.el5.x86_64.rpm
warning: nfs-utils-lib-devel-1.0.8-7.6.el5.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ID e8562897: NOKEY
error: Failed dependencies:
libnfsidmap.so.0()(64bit) is needed by nfs-utils-lib-devel-1.0.8-7.6.el5.x86_64
librpcsecgss.so.2()(64bit) is needed by nfs-utils-lib-devel-1.0.8-7.6.el5.x86_64
nfs-utils-lib = 1.0.8-7.6.el5 is needed by nfs-utils-lib-devel-1.0.8-7.6.el5.x86_64

 

[root@localhost NFS]# rpm -ivh nfs-utils-1.0.9-42.el5.x86_64.rpm
warning: nfs-utils-1.0.9-42.el5.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ID e8562897: NOKEY
error: Failed dependencies:
libldap-2.3.so.0()(64bit) is needed by nfs-utils-1:1.0.9-42.el5.x86_64
libnfsidmap.so.0()(64bit) is needed by nfs-utils-1:1.0.9-42.el5.x86_64
librpcsecgss.so.2()(64bit) is needed by nfs-utils-1:1.0.9-42.el5.x86_64
nfs-utils-lib >= 1.0.8-2 is needed by nfs-utils-1:1.0.9-42.el5.x86_64

 

安装rpm包过程中提示缺少若干库文件,添加后仍有问题,发现由于系统升级,按5.4的方法安装不可行,决定采用yum安装,结果不再报错。

[root@localhost NFS]# yum install nfs-utils
Loaded plugins: fastestmirror, security
Loading mirror speeds from cached hostfile
* base: mirror.steadfast.net
* extras: mirror.steadfast.net
* updates: mirror.steadfast.net
Setting up Install Process
Resolving Dependencies
–> Running transaction check
—> Package nfs-utils.x86_64 1:1.2.3-36.el6 will be installed
–> Processing Dependency: nfs-utils-lib >= 1.1.0-3 for package: 1:nfs-utils-1.2.3-36.el6.x86_64
–> Processing Dependency: libnfsidmap.so.0()(64bit) for package: 1:nfs-utils-1.2.3-36.el6.x86_64
–> Running transaction check
—> Package nfs-utils-lib.x86_64 0:1.1.5-6.el6 will be installed
–> Finished Dependency Resolution

Dependencies Resolved

=================================================================================
Package Arch Version Repository Size
=================================================================================
Installing:
nfs-utils x86_64 1:1.2.3-36.el6 base 319 k
Installing for dependencies:
nfs-utils-lib x86_64 1.1.5-6.el6 base 67 k

Transaction Summary
=================================================================================
Install 2 Package(s)

Total download size: 387 k
Installed size: 1.1 M
Is this ok [y/N]: y
Downloading Packages:
(1/2): nfs-utils-1.2.3-36.el6.x86_64.rpm | 319 kB 00:02
(2/2): nfs-utils-lib-1.1.5-6.el6.x86_64.rpm | 67 kB 00:00
———————————————————————————
Total 97 kB/s | 387 kB 00:03
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
Warning: RPMDB altered outside of yum.
Installing : 1:nfs-utils-1.2.3-36.el6.x86_64 1/2
Installing : nfs-utils-lib-1.1.5-6.el6.x86_64 2/2
Verifying : nfs-utils-lib-1.1.5-6.el6.x86_64 1/2
Verifying : 1:nfs-utils-1.2.3-36.el6.x86_64 2/2

Installed:
nfs-utils.x86_64 1:1.2.3-36.el6

Dependency Installed:
nfs-utils-lib.x86_64 0:1.1.5-6.el6

Complete!

 

2.配置NFS时问题

输入showmount –e 222.31.76.82检查RPC是否开启

报错如下:

[root@localhost ~]# clnt_create: RPC: Port mapper failure – Unable to receive: errno 113 (No route to host)

解决:

原因为NFS默认使用111端口,因此在iptables配置文件中打开111端口。

[root@localhost etc]# cat ./sysconfig/iptables

# Firewall configuration written by system-config-firewall

# Manual customization of this file is not recommended.

*filter

:INPUT ACCEPT [0:0]

:FORWARD ACCEPT [0:0]

:OUTPUT ACCEPT [0:0]

-A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT

-A INPUT -p icmp -j ACCEPT

-A INPUT -i lo -j ACCEPT

-A INPUT -m state –state NEW -m tcp -p tcp –dport 22 -j ACCEPT

-A INPUT -m state –state NEW -m tcp -p tcp –dport 80 -j ACCEPT

-A INPUT -m state –state NEW -m tcp -p tcp –dport 443 -j ACCEPT

-A INPUT -j REJECT –reject-with icmp-host-prohibited

-A FORWARD -j REJECT –reject-with icmp-host-prohibited

-A INPUT -p TCP –dport 111 -j ACCEPT

-A INPUT -p UDP –dport 111 -j ACCEPT

COMMIT

       再次检查RPC是否开启

[root@localhost etc]# RPC: Program not registered

        多次重启RPC和NFS仍然无效,关闭防火墙也不行,发现RPC还是没有启动,最后重新yum安装了rpcbind,结果RPC成功开启,并且挂载成功。问题可能是第一次安装不完整,上网查了好多也没解决,花了很长时间,结果问题很容易解决,但积累了经验,解决问题要从最基本的地方入手。

[root@localhost ~]# showmount -e 222.31.76.82
Export list for 222.31.76.82:
/opt/nfs *

[root@localhost ~]# mount -t nfs -o soft 222.31.76.82:/opt/nfs /opt/nfs

[root@localhost ~]# df -h
文件系统 容量 已用 可用 已用%% 挂载点

/dev/sda2 4.0G 2.9G 936M 76% /
tmpfs 3.9G 0 3.9G 0% /dev/shm
/dev/sda1 1008M 69M 889M 8% /boot
222.31.76.82:/opt/nfs
4.0G 3.7G 130M 97% /opt/nfs

    总体来说,安装NFS过程相对简单,问题都不复杂,掌握了如何在客户端挂载NFS文件系统,从中收获了很多解决问题的方法,感觉经验在一点点积累!

[转]保持程序员身体健康的7大招数

       自己的健康自己管理,意识到自己的健康的重要,不要勉强自己做一些会损害自己健康的事情,例如连续通宵等等。良好的健康,对自己,对家庭,对公司都是一笔财富。年轻的时候用健康换钱,上了年纪就不得不用钱来换健康了。

     程序员往往被要求不断的提高工作能力,技术水平,却很少被要求有自我管理健康的能力。

1.健康管理支撑着你的工作。

     从公司的角度考虑,一个经常患病的人,是不会被委以重任的。从个人角度考虑,经常患病给自己和家庭都带来很大的烦恼。俗话说身体是革命的本钱,有个好身体,干什么都有可能。

2. 简单的每日检查。

     首先,体重的检查。对程序员来说,每日测量一下体重是最可行的方法,每个人都有标准体重,通过每天的测量,你就可以有意识的通过减少饭量,多做运动来保持自己的体重。然后是吃饭,如果因为工作很晚才能吃饭的话,就考虑一下自己的睡觉时间,把饭量减一减。少吃油腻的东西,多吃蔬菜。每天喝一升的茶,多喝无糖的水。感到疲劳的时候吃点维生素。

3. 职业病的处方。

     程序员因为长时间保持坐姿,长时间面对电脑画面,容易引起肩膀疼,腰疼和眼睛疲劳。所以应该每工作一个小时就起身活动 5 分钟左右,这个活动包括身体的屈伸,肩部运动等等。同时,闭上眼睛转动眼球,使用眼药等对缓解眼睛疲劳比较有效。去厕所,去买东西的时候,做做这些,也算是对时间的有效利用吧。

4. 对付睡眠不足

     干IT的没有不加班的,所以很多时候就容易睡眠不足。为了保证睡眠时间就要合理的安排好自己的工作,分好优先级,把今天最应该干完的做完就可以了,然后早点回家睡觉。这一点,书里讲的我想有点牵强,在中国或许没有什么很好的办法来解决加班的问题,在全世界或许都是个问题。

5. 心理健康很重要。

     不要光注意身体,也要时常注意自己的心理健康,程序员常年面临各种各样的压力,不断重复的工作,保持自己的心理健康,也是一个非常重要的课题。方法很简单,就是自己奖励自己。解决了一个bug ,完成了一个复杂的算法,明白了一个需求,都可以适当的奖励自己。奖励的形式多种多样,总之自己喜欢什么就干什么。其实这里也给项目的领导者一个启示,就是要适当的对手下的程序员予以鼓励和奖励,完成了一个阶段计划,完成了一次测试,解决了一个关键问题,都可以组织大家轻松一下,有利于提高团队的凝聚力和个人的工作热情。

6.  尽情的放松。

    如果项目时间很长,结束遥遥无期或者项目陷入了泥潭,无法前进的时候,为了保持自己的工作劲头,不妨选择适当的一天,什么也不做,让自己好好放松,换换大脑,有利于更有效率的工作。

7. 最后,说一下简单的营养补给。

    平常吃点食物纤维和复合维生素,肩膀疼的时候多吃维生素E 比较有效,眼睛疲劳时多吃维生素A 。