分类 FPGA 下的文章

HDUSec-安全隔离网闸项目总结

比赛结束了,得给我们的项目做一个总结。

系统简介


我们作品的名称是HDUSec-安全隔离网闸,HDUSec是代表我们协会。作品主要是仿造工业网闸进行创新,

实现的主要功能是基于可重构的Xilinx FPGA,过滤外网到内网的文件,通过协议转化来安全单项传输文件,

同时还集成了报警,智能控制等模块。

系统实现


系统分成三个单元:文件缓存单元,系统控制单元,文件转发引擎。系统主要采用了分布式的架构,这里的

分布式是广义的,主要是一个系统分布在两块开发板上,两块都是Xilinx的,一块是Atlys,另一块Nexys3。

首先是Nexys3板卡,Nexy3板卡较Atlys,资源相对少了些,处理性能也低些,我们在Nexys3上采用了

MicroBlaze架构,通过对DDR内存控制器,PMode等控制模块的利化,通过PLB总线和板子的外部单物理层

网络芯片MicroRAM通信。在Microblaze架构上移植了Xilkernel,Xilkernel是Xilinx公司研发的轻型嵌入式系

统,Xilkernel采用的LWIP协议栈,LWIP是很轻型的协议栈,有它自己一套标准的 LWIP Socket API。我们

裁剪了基本的应用层协议,在LWIP只搭建了一个回显服务器和tftp服务器。整个Nexys3就够成了系统的文

件缓存单元,文件从外网到内网传送,文件会先存储到文件缓存单元的DDR上,等待系统控制单元的请求。

然后再说Atlys板卡,Atlys板卡是Sparnt-6系列的,系统控制单元和文件转发引擎在Atlys板卡上。我们在

Atlys板卡上采用的是OpenRISC架构,OpenRISC是OpenCORES下开源的项目,正是OpenRISC的开源,

可以根据开发者根据自己的需求实现对系统硬件的裁剪,OpenRISC的开源降低了项目的开发成本,也大

大缩短了项目开发的周期。在OpenRISC架构中我们采用的核心处理器是or3200,or3200是OpenRISC家

族中系能最好的。在OpenRISC上面移植了Linux 3.4.2的内核,当然因为移植了内核,就降低了Atlys的性

能。接下来就基本上是linux上面的开发了,在应用层我们搭建了一套web服务器,支持POST和GET请求,

设计不足就是Web服务器没有开线程池,当时主要是想到板子的并不是用于商用,反正是自己玩玩的。

Web服务器调用后台的cgi程序,后台的cgi接口是我定的,至于js,html,ajax则是囧哥和何少帮我完成

的。后台cgi调用的程序基本上我都以C为主,不过有些时候为了方便,就写了好多脚本,脚本里面主要是

awk,sed和grep等工具,就是C和Shell脚本混编构成了服务器的后台。其实我们在应用层做的工作挺多的

,我们设计了管理员和普通用户,都采用了身份验证机制。管理员登入之后,可以对系统进行全局设置,

主要是文件类型库,敏感词库,用户帐号等进行基本的管理,还有就是短信发送号码设置,最后就是用户

下载文件的日志记录和查看。

下面主要是文件转发引擎的工作,对于普通用户,经过身份验证之后,登入普通用户界面,这时候web服务

器会去向Nexys3板卡上的文件缓存单元请求DDR中的文件目录,目录的数据包会从Nexys3传输到Atlys,然

后由Atlys返回给客户端浏览器。用户看到在Nexy3的DDR中的文件目录,并且下载。用户点击下载,通过

POST包发送给Web服务器命令,Web服务器去Nexys3上下载指定的文件,文件到达Atlys,然后开始检测

文件类型是否与系统控制单元中预设文件类型符合,然后是检测文件内容,不合法的文件都移除到系统的隔

离区,等待管理员查看。在此过程中通过外接的GSM模块进行报警,以短信的形式发送给管理员。在web服

务器还设计了一套基于手机的管理界面,管理员可以通过手机访问系统,进行基本的系统管理。如果报警信

息,管理员通过手机登入,关闭系统网卡,并且可以通过发送短信打开系统工作状态。文件转发引擎只会转

发文件类型和内容都OK的文件,这里为了保证内网的安全,采用了协议转换的方式,由传统的TCP/IP协议

转换成了串口协议,传输到内网,从外保证就是系统被Hacker攻破了,也绝对不会影响到内网。为了保证文

件传送的可靠性,我们采用了基于连接的ZMODEM协议,ZMODEM是一种类似TCP一样存在错误校验的通

信协议,以牺牲效率来保证可靠性。

系统的创新和特色


  1. 系统是采用了分布式架构,系统分布在了两个不同的开发板上,为了保证系统的安全性,在两块不同的开发板上根据资源的限制分别移植了Microblaze和OpenRISC架构,并在各自软核上移植不同的内核。
  2. 系统的硬件支持是基于可重构的Xilinx FPGA的,可以根据开发者需求裁剪。
  3. 文件传送过程中采用了协议转化的形式,内网和外网不存在物理上的直接连接,仅仅是一个逻辑上的虚拟连接,更有效的保证了内网的安全。

cgi下dup2()问题

函数名: dup2
功 能: 复制文件句柄
用 法: int dup2(int oldhandle, int newhandle);

#include <unistd.h>

define STDIN_FILENO    0       /* Standard input.  */
#define STDOUT_FILENO   1       /* Standard output.  */
#define STDERR_FILENO   2       /* Standard error output.  */

问题描述:


在写一个小型web服务器的过程中,把返回的socket描述符sockfd用dup2函数复制给标准输出描述符,这样才调用cgi程序的时候对于所有原本要输出到标准输出的流全部都会写入到sockfd,返回给客户端。但是有一个问题:就是我想用lsz来传输一个文件,客户端一直没有返回。我查看了下进程,发现一直都卡在lsz里面的。我想了很久,发现 lsz 发送文件的过程中会有输出,这时候打输出就默认输出到sockfd里面了,导致我程序死了。也就是说怎么样实现cgi程序里,在需要和终端交互的时候实现交互?

代码:


/*************server.c*****************/
setenv("QUERY_STRING", cgiargs, 1); 			
Dup2(fd, STDOUT_FILENO);         /* Redirect stdout to client */		//把标准输出的句柄复制到文件句柄
Execve(filename, emptylist, environ); /* Run CGI program */

Execve里面执行的程序就是lsz,用于向串口传输文件。

问题解决:


cgi程序里面,主要做法:把不需要传回给sockfd的输出返回给终端就行了,那么就不会写到客户端的sockfd里面了。那么怎么实现呢?可以这样:因为在这个时候sockfd==STDOUT_FILENO,只需要把STDOUT_FILENO先保存下来oldsockfd,然后用open重新打开终端,然后用dup2把返回的描述符和STDOUT_FILENO联系在一起,这个时候输出又重定向到STDOUT_FILENO去了,然后输出结束,再用dup2把oldsockfd又和STDOUT_FILENO联系在一起。这时候输出又重定向到sockfd去了,下面是代码:
int oldsockfd = STDOUT_FILENO;
int ttyfd = open("/dev/tty",O_RDWR);
dup2(ttyfd,STDOUT_FILENO);
//do somethings 
dup2(STDOUT_FILENO,oldsockfd);

linux串口传输文件

需要从FPGA上通过串口把文件传输到PC上面,下面是代码。可以测试下串口的buffer大小,我电脑上的是4k多。

write.c

#include   <stdlib.h>           
#include   <stdio.h>
#include   <unistd.h>   
#include  <string.h>      
#include   <sys/types.h> 
#include   <sys/stat.h> 
#include   <fcntl.h>             
#include   <termios.h>         
#include   <errno.h>             
#include   <sys/time.h> 
#include   <time.h> 

#define BUFFER_SIZE 32               //这里可以优化,一次读取文件可以大点,分次写入串口buffer。
#define FALSE -1
#define TRUE 1

int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300,
	    B38400, B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = {38400,  19200,  9600,  4800,  2400,  1200,  300,
	    38400,  19200,  9600, 4800, 2400, 1200,  300, };

void set_speed(int fd, int speed);
int set_Parity(int fd,int databits,int stopbits,int parity);

int main(int argc,char *argv[])
{
	char *interface = NULL,*filename = NULL;

	if (argc < 2)
	{
		interface = "/dev/ttyUSB0";
		filename = "hello.txt"	;
	}
	else 
	{
		interface = argv[1];
		filename = argv[2];	
	}

	int fd=open(interface,O_RDWR|O_NOCTTY|O_NDELAY);   
	if(fd == -1)   
	{   
	    printf("%s Open   Error!\n",interface);   
	    return -1;   
	} 
	printf("open %s successfully !",interface);
	
	set_speed(fd,19200);
		if (set_Parity(fd,8,1,'N')== FALSE)
	{
		printf("Set Parity Error\n");
		exit(1);
	}


	int fp = open(filename,O_RDWR);
	if ( fp == -1 )
	{
		printf("open %s failured\n",filename);
		return -1;
	}
	int nread = 1;
	char buffer[BUFFER_SIZE] = {'\0'};
	int sum = 0;

	while(nread > 0)
	{
		int nwrite = 0;
		int tmp = 0,pos=0;	
		nread = read(fp,buffer,BUFFER_SIZE);	//一次要写进去的字节数
		printf("读取字节数 : %d bytes \n",nread);
		int size_write = nread;			//size_write是要本次要写入的总字节数	
		while (size_write > 0)
		{	
	//		int pos = 0>=nwrite?0:nwrite ;			//偏移
//			printf("pos = %d\n",pos);
			tmp = (nwrite > tmp)? nwrite : tmp;			//
			pos = tmp ;
			//printf("tmp = %d,pos %d \n",tmp,pos);
		        nwrite = write(fd,buffer + pos,size_write);	//nwrite一次写进去的字节数		
			if (nwrite == -1)
			{
				sleep (2);
				continue;
			}
			sum = sum + nwrite;			//nwrite 8
			printf("写入字节数 : %d,剩余字节数 : %d \n",sum,size_write);	
			size_write = size_write-nwrite;		//剩下要写进去的字节数				
		}
	}
	printf("sussfully  write %s\n",filename);
	close(fp);
	close(fd);
	return 0; 
}  

void set_speed(int fd, int speed)
{
	int   i;
	int   status;
	struct termios   Opt;
	tcgetattr(fd, &Opt);
	for ( i= 0;  i < sizeof(speed_arr) / sizeof(int);  i++)
	{
		if  (speed == name_arr[i])
		{
			tcflush(fd, TCIOFLUSH);
			cfsetispeed(&Opt, speed_arr[i]);
			cfsetospeed(&Opt, speed_arr[i]);
			status = tcsetattr(fd, TCSANOW, &Opt);
			if (status != 0)
			{
				perror("tcsetattr fd1");
				return;
			}
		}
		tcflush(fd,TCIOFLUSH);
	}
}

int set_Parity(int fd,int databits,int stopbits,int parity)
{
	struct termios options;
	if (tcgetattr( fd,&options)  !=  0)
	{
		perror("SetupSerial 1");
		return(FALSE);
	}
	options.c_cflag &= ~CSIZE;
	switch (databits) /*设置数据位数*/
	{
		case 7:
			options.c_cflag |= CS7;
			break;
		case 8:
			options.c_cflag |= CS8;
			break;
		default:
			fprintf(stderr,"Unsupported data size\n");
			return (FALSE);
	}
	switch (parity)
	{
		case 'n':
		case 'N':
			options.c_cflag &= ~PARENB;   /* Clear parity enable */
			options.c_iflag &= ~INPCK;     /* Enable parity checking */
			break;
		case 'o':
		case 'O':
			options.c_cflag |= (PARODD | PARENB);  /* 设置为奇效验*/ 
			options.c_iflag |= INPCK;             /* Disnable parity checking */
			break;
		case 'e':
		case 'E':
			options.c_cflag |= PARENB;     /* Enable parity */
			options.c_cflag &= ~PARODD;   /* 转换为偶效验*/  
			options.c_iflag |= INPCK;       /* Disnable parity checking */
			break;
		case 'S':
		case 's':  /*as no parity*/
			options.c_cflag &= ~PARENB;
			options.c_cflag &= ~CSTOPB;
			break;
		default:
			fprintf(stderr,"Unsupported parity\n");
			return (FALSE);
	}
	/* 设置停止位*/   
	switch (stopbits)
	{
		case 1:
			options.c_cflag &= ~CSTOPB;
			break;
		case 2:
			options.c_cflag |= CSTOPB;
			break;
		default:
			fprintf(stderr,"Unsupported stop bits\n");
			return (FALSE);
	}
	/* Set input parity option */
	if (parity != 'n')
		options.c_iflag |= INPCK;
	options.c_cc[VTIME] = 150; // 15 seconds
	options.c_cc[VMIN] = 0;

	tcflush(fd,TCIFLUSH); /* Update the options and do it NOW */
	if (tcsetattr(fd,TCSANOW,&options) != 0)
	{
		perror("SetupSerial 3");
		return (FALSE);
	}
	return (TRUE);
 }

read.c


#include   <stdlib.h>           
#include   <stdio.h>
#include   <unistd.h>   
#include  <string.h>      
#include   <sys/types.h> 
#include   <sys/stat.h> 
#include   <fcntl.h>             
#include   <termios.h>         
#include   <errno.h>             
#include   <sys/time.h> 
#include   <time.h> 

#define BUFFER_SIZE 32
#define MAX 1024
#define FALSE -1
#define TRUE 1

int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300,
	    B38400, B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = {38400,  19200,  9600,  4800,  2400,  1200,  300,
	    38400,  19200,  9600, 4800, 2400, 1200,  300, };

void set_speed(int fd, int speed);
int set_Parity(int fd,int databits,int stopbits,int parity);

int main(int argc,char *argv[])
{
	char *interface = NULL,*filename = NULL;

	if (argc < 2)
	{
		interface = "/dev/ttyACM0";
		filename = "hello.txt"	;
	}
	else 
	{
		interface = argv[1];
		filename = argv[2];	
	}
 
	int fd=open(interface,O_RDWR|O_NOCTTY|O_NDELAY);   
	if(fd == -1)   
	{   
	    printf("%s Open   Error!\n",interface);   
	    return -1;   
	} 
	printf("open %s successfully !",interface);
	
	set_speed(fd,19200);
	if (set_Parity(fd,8,1,'N')== FALSE)
	{
		printf("Set Parity Error\n");
		exit(1);
	}

	int fp = open(filename,O_RDWR|O_CREAT);
	if ( fp == -1 )
	{
		printf("open %s failured\n",filename);
		return -1;
	}

	int nread = 1,nwrite = 0;
	char buffer[BUFFER_SIZE] = {'\0'};
	while(1)
	{
		nread = read(fd,buffer,BUFFER_SIZE);   
		if (nread > 0)
		{
//			printf("读取 %d bytes \n",nread);
			nwrite = write(fp,buffer,nread);	
//			printf("写入 %d bytes \n",nwrite);
			if (nwrite <= 0)
			{		
				printf("write into file finished n");
				break;
			}
		}
	}

	printf("sussfully get %s\n",filename);
	return 0; 
}  

void set_speed(int fd, int speed)
{
	int   i;
	int   status;
	struct termios   Opt;
	tcgetattr(fd, &Opt);
	for ( i= 0;  i < sizeof(speed_arr) / sizeof(int);  i++)
	{
		if  (speed == name_arr[i])
		{
			tcflush(fd, TCIOFLUSH);
			cfsetispeed(&Opt, speed_arr[i]);
			cfsetospeed(&Opt, speed_arr[i]);
			status = tcsetattr(fd, TCSANOW, &Opt);
			if (status != 0)
			{
				perror("tcsetattr fd1");
				return;
			}
		}
		tcflush(fd,TCIOFLUSH);
	}
}

int set_Parity(int fd,int databits,int stopbits,int parity)
{
	struct termios options;
	if (tcgetattr( fd,&options)  !=  0)
	{
		perror("SetupSerial 1");
		return(FALSE);
	}
	options.c_cflag &= ~CSIZE;
	switch (databits) /*设置数据位数*/
	{
		case 7:
			options.c_cflag |= CS7;
			break;
		case 8:
			options.c_cflag |= CS8;
			break;
		default:
			fprintf(stderr,"Unsupported data size\n");
			return (FALSE);
	}
	switch (parity)
	{
		case 'n':
		case 'N':
			options.c_cflag &= ~PARENB;   /* Clear parity enable */
			options.c_iflag &= ~INPCK;     /* Enable parity checking */
			break;
		case 'o':
		case 'O':
			options.c_cflag |= (PARODD | PARENB);  /* 设置为奇效验*/ 
			options.c_iflag |= INPCK;             /* Disnable parity checking */
			break;
		case 'e':
		case 'E':
			options.c_cflag |= PARENB;     /* Enable parity */
			options.c_cflag &= ~PARODD;   /* 转换为偶效验*/  
			options.c_iflag |= INPCK;       /* Disnable parity checking */
			break;
		case 'S':
		case 's':  /*as no parity*/
			options.c_cflag &= ~PARENB;
			options.c_cflag &= ~CSTOPB;
			break;
		default:
			fprintf(stderr,"Unsupported parity\n");
			return (FALSE);
	}
	/* 设置停止位*/   
	switch (stopbits)
	{
		case 1:
			options.c_cflag &= ~CSTOPB;
			break;
		case 2:
			options.c_cflag |= CSTOPB;
			break;
		default:
			fprintf(stderr,"Unsupported stop bits\n");
			return (FALSE);
	}
	/* Set input parity option */
	if (parity != 'n')
		options.c_iflag |= INPCK;
	options.c_cc[VTIME] = 150; // 15 seconds
	options.c_cc[VMIN] = 0;

	tcflush(fd,TCIFLUSH); /* Update the options and do it NOW */
	if (tcsetattr(fd,TCSANOW,&options) != 0)
	{
		perror("SetupSerial 3");
		return (FALSE);
	}
	return (TRUE);
 }

嵌入式boa服务器搭建和移植

1.先下载源码 http://www.boa.org/ ==> boa-0.94.13.tar.g

2.tar -xvf boa-0.94.13.tar.g

3./configure

4.修改Makefile

CC =or32-linux-gcc

CPP = or32-linux-gcc–E

5.修改boa.c,注释下面几行

if (setuid(0) != -1) {
DIE("icky Linux kernel bug!");
}改为/*if (setuid(0) != -1) {
DIE("icky Linux kernel bug!");
}*/

6.修改文件compat.h

#define TIMEZONE_OFFSET(foo) foo##->tm_gmtoff
修改成
#define TIMEZONE_OFFSET(foo) (foo)->tm_gmtoff

7.make 编译,这时候就会生成一个boa的可执行文件

boa的配置文件是boa.conf,大概的配置是这样的:

Port 80   //服务访问端口

User 0
Group 0   

ErrorLog /var/log/boa/error_log //错误日志地址
AccessLog /var/log/boa/access_log  //访问日志文件

DocumentRoot /var/www  //HTML文档的主目录

UserDir public_html  //

DirectoryIndex index.html  //默认访问文件

DirectoryMaker /usr/lib/boa/boa_indexer

KeepAliveMax 1000   //一个连接所允许的HTTP持续作用请求最大数目

KeepAliveTimeout 10  //HTTP持续作用中服务器在两次请求之间等待的时间数,以秒为单位

MimeTypes /etc/mime.types  //指明mime.types文件位置

DefaultType text/plain  //文件扩展名没有或未知的话,使用的缺省MIME类型

CGIPath /bin:/usr/bin:/usr/local/bin   //提供CGI程序的PATH环境变量值

Alias /doc /usr/doc    //为路径加上别名

ScriptAlias /cgi-bin/ /var/www/cgi-bin/ //输入站点和CGI脚本位置

对于调试阶段,可以把主机的目录挂载到目标板上面,这样就方便调试。

假设主机的NFS共享目录是/NFS,在NFS下面建立一个www的文件夹,然后在www的文件夹下面建立images,cig-bin目录,还有一个index.html,可以随便找一个主页就可以了。在主机上

mkdir /NFS/www

mkdir /NFS/www/images

mkdir /NFS/www/cgi-bin

cp <dir>/index.html /NFS/www/

然后在板子上面建立/var/www的目录

mkdir /var/www

mount -t nfs -o nolock <主机IP>:/NFS/www /var/www //挂载目标www

板子上建立日志存放目录,在板子上:

mkdir /var/log

mkdir /var/log/boa

对于boa配置文件的移植,可以把主机上的boa.conf拷贝到主机的NFS共享目录/NFS/www下面。

对于mime.types,直接用主机上/etc/mime.types就行了,拷贝到/NFS/www下面。

对于boa可执行文件,拷贝到/NFS/www/下面。

在主机上:

cp /etc/mime.types /NFS/www/

cp <boa dir>/boa.conf /NFS/www/

cp <boa dir>/src/boa  /NFS/www/

然后再在板子上把上面共享的文件拷贝到自己系统上,注意此时只要对/var/www操作就行了,在主机上:

cp /var/www/mime.types /etc/mime.types

mkdir /etc/boa

cp /var/www/boa.conf  /etc/boa/boa.conf

cp /var/www/boa /sbin/boa

/sbin/boa 启动boa服务器

在浏览器里输入板子的IP就可以测试了。

ffmpeg+OpenCV Linux下安装和配置

前不久安装好了OpenCV,昨晚测试一个avi视频处理的时候,cvCreateFileCapture总是返回NULL,我怀疑是ffmpeg没有配置好。今天就把OpenCV和ffmpeg都删除了,重新安装了下!最好把旧版本都删除了!

ffmpeg安装


源码下载 : svn checkout svn://svn.mplayerhq.hu/ffmpeg/trunk ffmpeg

文件配置 : ./configure - -enable-able-shared - -enable-gpl - -enable-swscale

安装 : make && make install

所有的库文件默认安装在/usr/local/lib 下, 所有的头文件安装在 /usr/local/include/lib*/下

测试 : ffplay a.avi

- 阅读剩余部分 -

libcxcore.so.1: cannot open shared object file: No such file or director

运行一个opencv的文件时候出错:

libcxcore.so.1: cannot open shared object file: No such file or director

在系统里查找了libcxcore.so.1,结果没有找到.

解决方法:


http://rpm.pbone.net/index.php3/stat/26/dist/64/size/11141747/name/opencv-1.0.0-9.fc9.src.rpm

下载包,解压好之后进入到里面的目录,会发现一个lib文件夹,里面有所需要的*.so.*,把里面的都复制到/usr/local/lib下面

$ vim /etc/ld.so.conf

查看是否已经添加 /usr/local/lib

$ ldconf

ldconfig: /usr/local/lib/libml.so.1 不是符号连接

ldconfig: /usr/local/lib/libhighgui.so.1 不是符号连接

ldconfig: /usr/local/lib/libcv.so.1 不是符号连接

ldconfig: /usr/local/lib/libcvaux.so.1 不是符号连接

ldconfig: /usr/local/lib/libcxcore.so.1 不是符号连接

不管它,再次编译,若还是失败,就把刚才的*.so.*都复制到/usr/lib下

$ cp -r /usr/local/lib/* /usr/lib/

opencv linux 安装和配置

在fedora16 和 CentOS 下面配置OpenCV,由于不同主机装的软件的都不一样,所以不能一概而论

大概需要的开发套件:

pkgconfig  libpng  zlib libjpeg  libtiff libjasper

ffmepeg GTK+ 的基本库(这里可选,用到的时候再装也行)

下面是我的主机安装配置OpenCV。

opencv 下载


 http://sourceforge.net/projects/opencvlibrary/files/opencv-unix/2.2/

在centos和fedora16下面,一般都把用户的软件装在 /usr/local/xxx 下面


$ cp OpenCV-2.4.0.tar.bz2 /usr/local/

$ tar -xvf OpenCV-2.4.0.tar.bz2

$ cd  OpenCV-2.4.0

2.4.0的下面是以CMakeLists.txt形式

$ yum install cmake

$ cmake CMakeLists.txt

$ make && make install


OpenCV 会安装在 /usr/local/lib 目录和 /usr/local/include/opencv/

环境变量配置

$ vim /etc/ld.so.conf

最后一行加入 /usr/local/lib

$ ldconfig
或者

export LD_LIBRARY_PATH=/usr/local/lib

OpenCV测试

 
[cc lang="c"]
//drawing.c
#ifdef _CH_
#pragma package
#endif

#define CV_NO_BACKWARD_COMPATIBILITY

#ifndef _EiC
#include "cv.h"
#include "highgui.h"
#include
#include
#endif

#define NUMBER 100
#define DELAY 5
char wndname[] = "Drawing Demo";

CvScalar random_color(CvRNG* rng)
{
int icolor = cvRandInt(rng);
return CV_RGB(icolor&255, (icolor>>8)&255, (icolor>>16)&255);
}

int main( int argc, char** argv )
{
int line_type = CV_AA; // change it to 8 to see non-antialiased graphics
int i;
CvPoint pt1,pt2;
double angle;
CvSize sz;
CvPoint ptt[6];
CvPoint* pt[2];
int arr[2];
CvFont font;
CvRNG rng;
int width = 1000, height = 700;
int width3 = width*3, height3 = height*3;
CvSize text_size;
int ymin = 0;
// Load the source image
IplImage* image = cvCreateImage( cvSize(width,height), 8, 3 );
IplImage* image2;

// Create a window
cvNamedWindow(wndname, 1 );
cvZero( image );
cvShowImage(wndname,image);
cvWaitKey(DELAY);

rng = cvRNG((unsigned)-1);
pt[0] = &(ptt[0]);
pt[1] = &(ptt[3]);

arr[0] = 3;
arr[1] = 3;

for (i = 0; i< NUMBER; i++)
{
pt1.x=cvRandInt(&rng) % width3 - width;
pt1.y=cvRandInt(&rng) % height3 - height;
pt2.x=cvRandInt(&rng) % width3 - width;
pt2.y=cvRandInt(&rng) % height3 - height;

cvLine( image, pt1, pt2, random_color(&rng), cvRandInt(&rng)%10, line_type, 0 );
cvShowImage(wndname,image);
if(cvWaitKey(DELAY) >= 0) return 0;
}

for (i = 0; i< NUMBER; i++)
{
pt1.x=cvRandInt(&rng) % width3 - width;
pt1.y=cvRandInt(&rng) % height3 - height;
pt2.x=cvRandInt(&rng) % width3 - width;
pt2.y=cvRandInt(&rng) % height3 - height;

cvRectangle( image,pt1, pt2, random_color(&rng), cvRandInt(&rng)%10-1, line_type, 0 );
cvShowImage(wndname,image);
if(cvWaitKey(DELAY) >= 0) return 0;
}

for (i = 0; i< NUMBER; i++)
{
pt1.x=cvRandInt(&rng) % width3 - width;
pt1.y=cvRandInt(&rng) % height3 - height;
sz.width =cvRandInt(&rng)%200;
sz.height=cvRandInt(&rng)%200;
angle = (cvRandInt(&rng)%1000)*0.180;

cvEllipse( image, pt1, sz, angle, angle - 100, angle + 200,
random_color(&rng), cvRandInt(&rng)%10-1, line_type, 0 );
cvShowImage(wndname,image);
if(cvWaitKey(DELAY) >= 0) return 0;
}

for (i = 0; i< NUMBER; i++)
{
pt[0][0].x=cvRandInt(&rng) % width3 - width;
pt[0][0].y=cvRandInt(&rng) % height3 - height;
pt[0][1].x=cvRandInt(&rng) % width3 - width;
pt[0][1].y=cvRandInt(&rng) % height3 - height;
pt[0][2].x=cvRandInt(&rng) % width3 - width;
pt[0][2].y=cvRandInt(&rng) % height3 - height;
pt[1][0].x=cvRandInt(&rng) % width3 - width;
pt[1][0].y=cvRandInt(&rng) % height3 - height;
pt[1][1].x=cvRandInt(&rng) % width3 - width;
pt[1][1].y=cvRandInt(&rng) % height3 - height;
pt[1][2].x=cvRandInt(&rng) % width3 - width;
pt[1][2].y=cvRandInt(&rng) % height3 - height;

cvPolyLine( image, pt, arr, 2, 1, random_color(&rng), cvRandInt(&rng)%10, line_type, 0 );
cvShowImage(wndname,image);
if(cvWaitKey(DELAY) >= 0) return 0;
}

for (i = 0; i< NUMBER; i++)
{
pt[0][0].x=cvRandInt(&rng) % width3 - width;
pt[0][0].y=cvRandInt(&rng) % height3 - height;
pt[0][1].x=cvRandInt(&rng) % width3 - width;
pt[0][1].y=cvRandInt(&rng) % height3 - height;
pt[0][2].x=cvRandInt(&rng) % width3 - width;
pt[0][2].y=cvRandInt(&rng) % height3 - height;
pt[1][0].x=cvRandInt(&rng) % width3 - width;
pt[1][0].y=cvRandInt(&rng) % height3 - height;
pt[1][1].x=cvRandInt(&rng) % width3 - width;
pt[1][1].y=cvRandInt(&rng) % height3 - height;
pt[1][2].x=cvRandInt(&rng) % width3 - width;
pt[1][2].y=cvRandInt(&rng) % height3 - height;

cvFillPoly( image, pt, arr, 2, random_color(&rng), line_type, 0 );
cvShowImage(wndname,image);
if(cvWaitKey(DELAY) >= 0) return 0;
}

for (i = 0; i< NUMBER; i++)
{
pt1.x=cvRandInt(&rng) % width3 - width;
pt1.y=cvRandInt(&rng) % height3 - height;

cvCircle( image, pt1, cvRandInt(&rng)%300, random_color(&rng),
cvRandInt(&rng)%10-1, line_type, 0 );
cvShowImage(wndname,image);
if(cvWaitKey(DELAY) >= 0) return 0;
}

for (i = 1; i< NUMBER; i++)
{
pt1.x=cvRandInt(&rng) % width3 - width;
pt1.y=cvRandInt(&rng) % height3 - height;

cvInitFont( &font, cvRandInt(&rng) % 8,
(cvRandInt(&rng)%100)*0.05+0.1, (cvRandInt(&rng)%100)*0.05+0.1,
(cvRandInt(&rng)%5)*0.1, cvRound(cvRandInt(&rng)%10), line_type );

cvPutText( image, "Testing text rendering!", pt1, &font, random_color(&rng));
cvShowImage(wndname,image);
if(cvWaitKey(DELAY) >= 0) return 0;
}

cvInitFont( &font, CV_FONT_HERSHEY_COMPLEX, 3, 3, 0.0, 5, line_type );

cvGetTextSize( "OpenCV forever!", &font, &text_size, &ymin );

pt1.x = (width - text_size.width)/2;
pt1.y = (height + text_size.height)/2;
image2 = cvCloneImage(image);

for( i = 0; i < 255; i++ )
{
cvSubS( image2, cvScalarAll(i), image, 0 );
cvPutText( image, "OpenCV forever!", pt1, &font, CV_RGB(255,i,i));
cvShowImage(wndname,image);
if(cvWaitKey(DELAY) >= 0) return 0;
}

// Wait for a key stroke; the same function arranges events processing
cvWaitKey(0);
cvReleaseImage(&image);
cvReleaseImage(&image2);
cvDestroyWindow(wndname);

return 0;
}

#ifdef _EiC
main(1,"drawing.c");
#endif

[/cc]
$ g++ `pkg-config opencv - -libs - -cflags opencv` drawing.c -o drawing
$ ./drawing

OK!!

NFS 搭建

最近做嵌入式开发的时候,需要NFS加载文件系统,顺便搭建了一个NFS。

NFS:Network File System


功能也就是能把远程网络的文件挂载到NFS Server上,在Server上看来,客户端的挂载的目录就像自己的子目录一样,可以对它操作。所以,对于嵌入式系统的调试是很方便的。

NFS支持的功能很多,所以对应的端口号是不固定的,是随机分配的,但都是小于1024。那么客户机是怎么连接到NFS Server上去的呢?这里有一个RPC的东西来支持。

RPC:(Remote Procedure Call Protocol)


远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。RPC采用客户机/服务器模式。请求程序就是一个客户机,而服务提供程序就是一个服务器。首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息的到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行。
RPC在NFS搭建过程钟的功能就是在Server上分配端口号,可以让客户端能从远程连接上Server。RPC固定采用111端口监听。

- 阅读剩余部分 -

make menuconfig error

OS : ubuntu 10.10

# make ARCH=microblaze menuconfig

*** Unable to find the ncurses libraries or the
*** required header files.
*** 'make menuconfig' requires the ncurses libraries.
***
*** Install ncurses (ncurses-devel) and try again.
***
make[1]: *** [scripts/kconfig/dochecklxdialog] Error 1
make: *** [menuconfig] Error 2

# sudo apt-get install libncurses5-dev

OK!

 

mjpg-streamer 安装

mjpg-streamer 源码


[root@fire ~]# svn co https://mjpg-streamer.svn.sourceforge.net/svnroot/mjpg-streamer mjpg-streamer

[root@fire mjpg-streamer]# ls -l
总用量 24
drwxr-xr-x. 3 root root 4096 4月 29 11:31 doc
drwxr-xr-x. 4 root root 4096 4月 29 11:31 mjpeg-client
drwxr-xr-x. 6 root root 4096 4月 29 11:31 mjpg-streamer
drwxr-xr-x. 6 root root 4096 4月 29 11:31 mjpg-streamer-experimental
drwxr-xr-x. 3 root root 4096 4月 29 11:31 udp_client
drwxr-xr-x. 3 root root 4096 4月 29 17:07 uvc-streamer

编译:


[root@fire mjpg-streamer/mjpg-streamer-experimental]# make

[root@fire mjpg-streamer/uvc-streamer]# make (这里会编译下面的所有组件)

这里可能会出现错误,显示linux/videodev.h找不到,这是因为内核版本太高的原因,videodev.h这个接口不支持了。具体解决方案google下就可以了。我后来是换了ubuntu 10.10然后就能顺利配置了。

[root@fire mjpg-streamer/mjpg-streamer-experimental]# ./start.sh

如果启动后显示

Unable to set format: Invalid argument
Init v4L2 failed !! exit fatal
i: init_VideoIn failed

查看http://www.firefoxbug.com/?p=942

查看视频流


本机查看输入 http://localhost:8080/

其它电脑查看输入:  http://本机ip:8080/

mjpg-streamer:Init v4L2 failed

系统:ubuntu 10.10

启动: ./start.sh

错误内容:

root@fire:~/mjpg-streamer/mjpg-streamer-experimental# ./start.sh
MJPG Streamer Version: svn rev: 3:160
 i: Using V4L2 device.: /dev/video0
 i: Desired Resolution: 640 x 480
 i: Frames Per Second.: -1
 i: Format............: JPEG
Unable to set format: 1196444237 res: 640x480
 Init v4L2 failed !! exit fatal
 i: init_VideoIn failed

错误原因:
市面上大部分摄像头都是支持YUV的,而不是JPEG的。mjpg-stream支持JPEG和YUV两种格式。

[fire@fire mjpg-streamer]$ cd mjpg-streamer-experimental/plugins/input_uvc/
[fire@fire input_uvc]$ vim input_uvc.c

int input_init(input_parameter *param, int id)
{
    char *dev = "/dev/video0", *s;
    int width = 640, height = 480, fps = -1, format = V4L2_PIX_FMT_MJPEG, i;

    /* initialize the mutes variable */
    if(pthread_mutex_init(&cams[id].controls_mutex, NULL) != 0) {
        IPRINT("could not initialize mutex variable\n");
        exit(EXIT_FAILURE);
    }
.......................

format = V4L2_PIX_FMT_YUYV
以上就设置了默认的图像格式,重新把模块编译,之后就成功了!

linux下GTK+配置

上面是linux下GTK+配置所需要的库,关于各个库的功能,查看http://www.gtk.org/overview.php,至于库的下载在http://www.gtk.org/download/linux.php

linux下GTK+的一键安装和配置:(fedora16和centos下配置成功)


必要组件:

# yum install gtk2 gtk2-devel gtk2-devel-docs

可选组件:

# yum install gnome-devel gnome-devel-docs

安装好之后,写个程序测试下
[cc lang="c"]
#include

int main(int argc, char *argv[])
{
GtkWidget *windows;
gtk_init(&argc,&argv);

windows = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_widget_show(windows);

gtk_main();

return 0;
}
[/cc]

GTK+程序的编译链接执行


$ gcc -o simple simple.c `pkg-config --libs --cflags gtk+-2.0`
$ ./simple
若出现对话框代表成功!