分类 C/C++ 下的文章

linux named pipe(FIFO)

无名管道应用的一个重大限制是它没有名字,因此,只能用于具有亲缘关系的进程间通信,在有名管道(named pipe或FIFO)提出后,该限制得到了克服。FIFO不同于管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存在于文件系统中。这样,即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过FIFO相互通信(能够访问该路径的进程以及FIFO的创建进程之间),因此,通过FIFO不相关的进程也能交换数据。值得注意的是,FIFO严格遵循先进先出(first in first out),对管道及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾。它们不支持诸如lseek()等文件定位操作。
管道的缓冲区是有限的(管道制存在于内存中,在管道创建时,为缓冲区分配一个页面大小)
管道所传送的是无格式字节流,这就要求管道的读出方和写入方必须事先约定好数据的格式,比如多少字节算作一个消息(或命令、或记录)等等

FIFO往往都是多个写进程,一个读进程。可以参考我之前的博客 http://blog.csdn.net/firefoxbug/article/details/7358715

- 阅读剩余部分 -

Nginx 配置文件详解

nginx.conf 主要配置信息

http{
	server{
#		listen IP:port
#		listen *:IP
		listen 127.0.0.1:80;
		
		server_name _;		#默认匹配
		location / {	#URL访问路径匹配,可以多个location
			index index.php;
			root html;	#nginx 安装路径 相对路径	
		}
		location = / {
				
		}
	}

	server{

		location / {	#URL访问路径匹配,可以多个location
				
		}
	}
}

nginx配置文件主要是Http字段,一个Http字段里面可以有多个字段,一个server字段代表一个虚拟主机。一个server里面可以有多个字段,每个location代表一个URI资源。下面分别介绍基本配置:

==================================================================

location :


location:不同资源请求的路径
location +  [= | ~ | ~* |^~ | @ ]

= : 精确匹配
比如 /bbs
不加 = ,则表示bbs下所有文件目录,包括子目录
加 = ,仅表示bbs下的文件,不包括子目录

^~ :禁止匹配正则表达式

~ : 正则表达式,模式匹配,区分字符大小写
~*:正则表达式,模式匹配,不区分字符大小写

location /  {
         RA : 匹配 / 下面所有文件,包括子目录
}

location = / {
        RB : 只匹配 / 目录本身,不包括子目录
}

location  ^~ /images/ {
        RC
}

location  ~* \.(gif|jpg|jpeg)$  {
       RD
}

1. / ==>> RB
2. /a/b/c ==>> RA
3. /images/gif ==>> RC
4. /documents/1.jpg ==>> RD

==================================================================

root:


root  path
server中:表示全局的,对所有的location都有意义。

location:局部的资源定义

location /a/ {
         root /var/www/;
}

location / 就代表 location 里面的 root,若是location里的 root 未定义,就从 server 里面继承!

/a/1.html = /var/www/a/1.html

==================================================================

alias:


location  ~  ^/images/(.*)$  {
         alias /var/www/files/$1
}

URI: /images/1.txt ==>> /var/www/files/1.txt

location  /i/  {
          alias /var/www/
}

URI : /i/1.html ==>> /var/www/1.html

==================================================================

Linux下十六进制转成中文

在实现web服务器一项功能中:在处理post包数据段的内容是以一个字节一个字节读取的,所以如果post的

内容是中文的话,输出的时候会变成十六进制,那么怎么把十六进制再转成中文呢?

#include 
#include 
#include 

void ansiToutf8(char *src,char *desStr);

int main()
{
	char desStr[200]= {'\0'};
	char *p = "%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%EF%BC%88%E7%AC%AC%E4%B8%89%E7%89%88%EF%BC%89";	
	ansiToutf8(p,desStr);
	return 0;
}

void ansiToutf8(char *src,char *desStr)
{
	if(*src == '%')		//是中文
	{
		int des[200] = {0};
		int i = 0,j = 0;
		while(*(src+i) != '\0')
		{
			char buf[4] = {'\0'};		
			strncpy(buf,src+i,3);
			printf("%s\n",buf);
			sscanf(buf,"%%%x",&des[j]);
			printf("%d\n",des[j]);
			sprintf(desStr,"%s%c",desStr,des[j]);
			i = i + 3;
			++j;
		}
		printf("%s",desStr);
	}
}

转换后的结果就是
$ 程序设计(第三版)

setenv,getenv,fork

我们在实现CGI程序的时候,有时候会用setenv设置环境变量传递给子进程。那么父进程是怎么传递给子进程的呢?

 
[cc lang="c"]
//father.c
#include
#include
#include
#include
#include

extern char **environ;

int main()
{
char *str = "Hello From Father";
char *emptylist[] = { NULL, };
char *filename = "./child";

if(fork() == 0)
{
setenv("QUERY_STRING",str,1);
if (execve(filename, emptylist, environ) < 0)
{
printf("Execve error");
}
}
wait(NULL);
return 0;
}
[/cc]

[cc lang="c"]
//child.c
#include
#include
#include

int main()
{
printf("this is in son process\n");
char *p2 = (char *)getenv("QUERY_STRING");
if ( p2 )
printf("%s\n",p2);

return 0;
}
[/cc]
extern char **environ
这句话指向的就是环境变量的字符串数组。

libc中定义的全局变量environ指向环境变量表,environ没有包含在任何头文件中,所以在使用时要用extern声明。要是没有extern就会无法在子进程中获取环境变量。下面看一个environ获取环境变量获取的例子:
[cc lang="c"]
#include
#include
#include
#include
#include

extern char **environ;

int main()
{
char **p = environ;
while (*p != NULL)
{
printf("%s (%p)\n", *p, *p);
*p++;
}
return 0;
}
[/cc]
另外还要注意的一点就是,在setenv设置环境变量的时候是不能随便设置的,比如你要设置HOLLO=“hello”,这是不行的。为什么呢?调用fork产生子进程的时候,子进程会做一份父进程环境变量的拷贝,因为前面说了,拷贝就是通过environ来实现的,而environ是已经定义好的了。你要是非想用setenv传递环境变量,那么就只能用系统的环境变量来作为临时交换进行传递。

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);
 }

自己动手学TCP/IP--tftp协议

TFTP(Trivial File Transfer Protocol,简单文件传输协议

1.tftp的服务端口号是69

2.tftp是基于udp协议的

3.tftp是明文传输的,是一种比较轻量型的协议,一般用于bootloader加载内核

TFTP工作流程

服务端开启tftp服务,tftp是一种stand_alone服务,不是常驻内存的,是在有需要的时候才去调用的。首先,客户端发送一个读(RRQ:2个字节)或者写(WRQ:2个字节)的请求,数据包的目标端口是69。对于读或者写的报文格式如下:

RRQ/WRQ(2个字节)+文件名(N字节)+0(1字节)+模式(N字节)+0(1字节)

目前模式字段主要有2种:netascii,这是8位的ASCII码形式;另一种是octet,这是8位源数据类型。对于netascii是把回车和换行(CR/LF)解释成两个字节的。可以查看http://www.firefoxbug.com/?p=1041

tftp-server接收到数据包:如果是发现是读(RRQ),就重新随机分配一个端口,直接发送数据(DATA:2个字节)+块编号(2个字节),然后是0~512字节数据包。客户端接收到数据包,发给服务端(ACK:2个字节)+块编号(2个字节)。如果是普通的数据包,那么数据段的大小一定是512字节,如果是最后一个数据包,肯定是小于512字节的。tftp就是通过发现了一个数据段小于512字节的数据包来声明结束文件的传输了。那么一个要传输的文件刚还是512字节的整数倍怎么办呢?tftp会在最后传输一个数据段大小是0包。

tftp-server接收到数据包:如果发现是写(WRQ),服务端就发回(ACK:2个字节)+(块编号0:2个字节)的包,接着客户端就发送(DATA:2个字节)+(块编号1:2个字节)+数据段给服务端,服务端发回(ACK:2个字节)+(块编号1:2个字节)。。。依次发送。

错误信息是系统自定义的,格式主要是error(2个字节)+错误码(2个字节)+错误信息(N个字节)

下面是tftp数据包的格式图

下面是C语言解析tftp包的一小段代码:

struct tftphdr {
short th_opcode; /* packet type */
union {
unsigned short tu_block; /* block # */
short tu_code; /* error code */
char tu_stuff[1]; /* request packet stuff */
} __attribute__ ((__packed__)) th_u;
char th_data[1]; /* data or error string */
} __attribute__ ((__packed__));

// 解析udp包,packet_buffer是用rawsocket抓出来的以太网包,
void ParseUDPPacket(unsigned char *packet_buffer)
{
struct ethhdr *eth_header;//以太网头
struct iphdr *ip_header; //ip头
struct udphdr *udp_header; //tcp头
eth_header = (struct ethhdr*)packet_buffer;
ip_header = (struct iphdr*)(packet_buffer + sizeof(struct ethhdr));
udp_header = (struct udphdr*)(packet_buffer + sizeof(struct ethhdr) + ip_header->ihl*4);
unsigned char *data = NULL;
data = (packet_buffer + sizeof(struct ethhdr) + ip_header->ihl*4 + 8);//8代表UDP包头
struct tftphdr *tp = (struct tftphdr *)data; // /usr/include/arpa/tftp.h
tftp_print(data,ntohs(udp_header->len)-8); //ntohs(udp_header->len)-8表示udp数据包长度
}

/*
* Print trivial file transfer program requests
*/
void tftp_print(register const u_char *bp, u_int length)
{
register const struct tftphdr *tp;
register const u_char *p;
register int opcode,i;
static char tstr[] = " [|tftp]";
char buffer[520] = {'\0'};
tp = (const struct tftphdr *)bp;

// printf(" %d", length);
// printf("length of tftp_data = %d\n",length);

/* Print tftp request type */

opcode = EXTRACT_16BITS(&tp->th_opcode);
printf(" %s",tok2str(op2str, "tftp-#%d", opcode));
/* Bail if bogus opcode */

switch (opcode) {

case RRQ:
break;

case WRQ:
break;

case ACK:
break;

case DATA:
break;

case ERROR:
break;

default:
/* We shouldn't get here */
printf("(unknown #%d)", opcode);
break;
}
return;
}

详细的可以查看tcpdump的源码。

matlab小程序

输入一个日期,输出是第几天

year=input('year : ')
month=input('month : ')
day=input('day : ')

year1=[31,28,31,30,31,30,31,31,30,31,30,31];
year2=[31,29,31,30,31,30,31,31,30,31,30,31];
%isloopyear=0
if mod(year,4)==0||(mod(year,4)==0 && mod(year,100)~=0)
    isloopyear=1
else
    isloopyear=0
end
sum=0
if isloopyear==1
    for n=1:month-1
        sum=sum+year2(n);
    end
else
    for n=1:month-1
        sum=sum+year1(n);
    end
end
sum=sum+day

gcc链接静态库和动态库

//hello.c
#include 

void print_hello()
{
	printf("HelloWorld ");
}

//main.c
#include 
#include "hello.h"

int main()
{
	print_hello();
        printf("%d",HELLO);
	return 0;
}

//hello.h
#define HELLO 9999
void print_hello();

其中 hello.c 和 main.c 在同一个目录下, hello.h在上一个目录。

先生成 xxx.o 文件
$ gcc hello.c -c ==> hello.o
$ gcc main.c -c ==> error : no hello.h
$ gcc main.c -c -I ../ ==> main.o -I 指定头文件的搜索目录( I 是大小的 i)
$ ls ==> hello.o main.o hello.c main.c

- 阅读剩余部分 -

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!!

undefined reference to `pthread_create'

pthread_create()


头文件


#include<pthread.h>

函数声明


int pthread_create(pthread_t*restrict tidp,const pthread_attr_t *restrict_attr,void*(*start_rtn)(void*),void *restrict arg);

返回值


若成功则返回0,否则返回出错编号

 问题出现:


在链接 pthread_create 的时候出现:undefined reference to `pthread_create'

 问题原因:


thread 库不是 Linux 系统默认的库,连接时需要使用静态库 libpthread.a,所以在使用pthread_create()创        建线程,以及调用 pthread_atfork()函数建立fork处理程序时,需要链接该库。

 问题解决:


在链接的时候加-lpthread

# gcc -g test.c -o test  -lpthread

linux下添加libpcap模块

  1. 先从 http://www.linuxfromscratch.org/blfs/view/svn/basicnet/libpcap.html 下载libpcap-1.1.1.tar.gz
  2. # tar -xvf libpcap-1.1.1.tar.gz 解压
  3. cd libpcap-1.1.1/ 进入到路径下
  4. ./configure && make
  5. 这时候可能会提示:configure : error : Your operating system's lex is insufficient to compile .XXXXXXXXX 这时候只需要安装下flex #yum install flex
  6. 接着就是 # make install
  7. 这时候又可能会提示yacc -d grammar.y

    make: yacc:命令未找到

    make: *** [grammar.c] 错误 127。  # yum install byacc.i686即可
  8. 最后重新# make install 就会成功,然后去/usr/include/下查看,会出现pcap/和.h文件
  9. 接下来就可以使用库了,只要在gcc 最后加 -lpcap 即可# gcc test.c -o test -lpcap

     

    另外可以把libpcap编译生成的 .o 文件都拷贝到自己的一个目录下面,然后gcc -L XXX/*.o 来实现源代码的链接!

Makefile使用

make能作为工程管理器,把不同的源文件进行编译链接到一个工程。make每次读取的都是Makefile,它也就是普通的文本文件,只是它有它自己的语法。make主要通过时间戳的原理来进行管理工程。比如main.c的文件总是会main.o的文件更旧,因为main.o是依赖于main.c而产生的。一旦出现main.c的文件比main.o时间还新,那说明main.c肯定是被更新了,这个时候make就会把该文件重新编译。

- 阅读剩余部分 -

双栈

双栈意思就是双向栈,基本思想就是在一段内存里面,栈从两边分别向中间生长,这样可以提高内存的利用率。下面是C的实现代码,仅仅是基本的功能,重在于思想。

- 阅读剩余部分 -

链表逆置

上次用堆栈实现对链表的逆置,比较麻烦。这次换了个算法,下面主要有两种实现算法。

算法一


首先想到的肯定是创建一个新的空链表,然后把旧的链表中的元素通过指针p从头到尾遍历,每遍历一个,就把该元素从链表中脱离,添加到新的链表的头部,新建空链表的时候可以初始化一个空的无用节点(仅仅是为了操作方便)。

算法二


不通过新建一个新链表,具体是让第一个节点的指针域为NULL,第二个指针域指向第一个节点,第三个指向第二个~~~~~~L指向最后一个节点。

- 阅读剩余部分 -

栈溢出

不久前醒哥发给我一些代码,说是讲栈溢出的危害,代码如下:

[code]
#include <stdio.h>

int cp (char *p)
{
int a;
char b[8];
a=strcmp(p,"1234567");
strcpy(b,p);
return a;
}

int main()
{
int v=0;
char p[1024];
while(1)
{
printf("please input password: ");
scanf("%s",p);
v = cp(p);
if(v)
{
printf("incorrect password!\n\n");
}
else
{
printf("Congralations \n\n");
break;
}
}
return 0;
}

[/code]

- 阅读剩余部分 -