<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>龍昌博客</title>
	<atom:link href="http://www.xefan.com/feed" rel="self" type="application/rss+xml" />
	<link>http://www.xefan.com</link>
	<description>关注Linux及开源信息</description>
	<lastBuildDate>Sun, 20 May 2012 04:48:17 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Linux串口操作</title>
		<link>http://www.xefan.com/archives/83757.html</link>
		<comments>http://www.xefan.com/archives/83757.html#comments</comments>
		<pubDate>Sun, 20 May 2012 04:48:17 +0000</pubDate>
		<dc:creator>龍昌</dc:creator>
				<category><![CDATA[编程开发]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.xefan.com/?p=83757</guid>
		<description><![CDATA[1、所需的头文件 #include &#60;stdio.h&#62; #include &#60;stdlib.h&#62; #include &#60;unistd.h&#62; //unix标准函数 #include &#60;sys/types.h&#62; #include &#60;sys/stat.h&#62; #include &#60;fcntl.h&#62; //文件控制 #include &#60;termios.h&#62; //POSIX中断控制 #include &#60;errno.h&#62; 2、打开串口 fd = open(“/dev/ttyUSB0&#8243;, O_RDWR); 3、设置波特率 最基本的串口设置包括波特率、校验位和停止位设置，主要使用termios.h头文件中定义的termios结构，如下： struct termios { tcflag_t c_iflag; //输入模式标志 tcflag_t c_oflag; //输出模式标志 tcflag_t c_cflag; //控制模式标志 tcflag_t &#8230; <a href="http://www.xefan.com/archives/83757.html">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>1、所需的头文件</p>
<p>#include &lt;stdio.h&gt;<br />
#include &lt;stdlib.h&gt;<br />
#include &lt;unistd.h&gt;     //unix标准函数<br />
#include &lt;sys/types.h&gt;<br />
#include &lt;sys/stat.h&gt;<br />
#include &lt;fcntl.h&gt;      //文件控制<br />
#include &lt;termios.h&gt;    //POSIX中断控制<br />
#include &lt;errno.h&gt;</p>
<p>2、打开串口<br />
fd = open(“/dev/ttyUSB0&#8243;, O_RDWR);</p>
<p>3、设置波特率<br />
最基本的串口设置包括波特率、校验位和停止位设置，主要使用termios.h头文件中定义的termios结构，如下：<br />
struct termios<br />
{<br />
    tcflag_t c_iflag;   //输入模式标志<br />
    tcflag_t c_oflag;   //输出模式标志<br />
    tcflag_t c_cflag;   //控制模式标志<br />
    tcflag_t c_lflag;   //本地模式标志<br />
    cc_t c_line;<br />
    cc_t c_cc[NCC];<br />
}</p>
<p>4、设置数据位、停止位和校验位<br />
8位数据位、无校验位：<br />
Opt.c_cflag &amp;= ~PARENB;<br />
Opt.c_cflag &amp;= ~CSTOPB;<br />
Opt.c_cflag &amp;= ~CSIZE;<br />
Opt.c_iflag |= CS8<br />
7位数据位、奇校验<br />
Opt.c_cflag |= PARENB;<br />
Opt.c_cflag |= PARODD;<br />
Opt.c_cflag &amp;= ~CSTOPB;<br />
Opt.c_cflag &amp;= ~CSIZE;<br />
Opt.c_cflag |= CS7;<br />
7位数据位、偶校验<br />
Opt.c_cflag |= PARENB;<br />
Opt.c_cflag &amp;= ~PARODD;<br />
Opt.c_cflag &amp;= ~CSTOPB;<br />
Opt.c_cflag &amp;= CSIZE;<br />
Opt.c_cflag |= CS7;<br />
7位数据位、Space校验<br />
Opt.c_cflag &amp;= ~PARENB;<br />
Opt.c_cflag &amp;= ~CSTOPB;<br />
Opt.c_cflag &amp;= ~CSIZE;<br />
Opt.c_cflag |= CS7;</p>
<p>5、读写串口<br />
读使用read函数；写使用write函数。</p>
<p>6、关闭串口<br />
close(fd);</p>
<p>例子：</p>
<pre class="brush: cpp; title: ; notranslate">
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;unistd.h&gt;     //unix标准函数
#include &lt;sys/types.h&gt;
#include &lt;sys/stat.h&gt;
#include &lt;fcntl.h&gt;      //文件控制
#include &lt;termios.h&gt;    //POSIX中断控制
#include &lt;errno.h&gt;

#define TRUE    1
#define FALSE   0
#define SERIAL  &quot;/dev/ttyUSB0&quot;

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

//设置波特率
void SetSpeed(int fd, int speed)
{
    int i;
    struct termios Opt; //定义termios结构

    if (tcgetattr(fd, &amp;Opt) != 0)
    {
        perror(&quot;tcgetattr fd&quot;);
        return;
    }
    for (i=0; i&lt;sizeof(speed_arr)/sizeof(int); i++)
    {
        if (speed == name_arr[i])
        {
            tcflush(fd, TCIOFLUSH);
            cfsetispeed(&amp;Opt, speed_arr[i]);
            cfsetospeed(&amp;Opt, speed_arr[i]);
            //tcsetattr函数标志：
            //TCSANOW:立即执行而不等待数据发送或者接受完成
            //TCSADRAIN:等待所有数据传递完成后执行
            //TCSAFLUSH:Flush input and output buffers and make the change
            if (tcsetattr(fd, TCSANOW, &amp;Opt) != 0)
            {
                perror(&quot;tcsetattr fd&quot;);
                return;
            }
            tcflush(fd, TCIOFLUSH);
        }
    }
}

//设置数据位、停止位和校验位
int SetParity(int fd, int databits, int stopbits, int parity)
{
    struct termios Opt;
    if (tcgetattr(fd, &amp;Opt) != 0)
    {
        perror(&quot;tcgetattr fd&quot;);
        return FALSE;
    }
    Opt.c_cflag |= (CLOCAL | CREAD);    //一般必设置的标志
    switch (databits)                   //设置数据位
    {
        case 7:
        {
            Opt.c_cflag &amp;= ~CSIZE;
            Opt.c_cflag |= CS7;
            break;
        }
        case 8:
        {
            Opt.c_cflag &amp;= ~CSIZE;
            Opt.c_cflag |= CS8;
            break;
        }
        default:
        {
            fprintf(stderr, &quot;Unsupport data size.\n&quot;);
            return FALSE;
        }
    }
    switch (parity)                     //设置校验位
    {
        case 'n':
        case 'N':
        {
            Opt.c_cflag &amp;= ~PARENB;     //清除校验位
            Opt.c_iflag &amp;= ~INPCK;      //enable parity checking
            break;
        }
        case 'o':
        case 'O':
        {
            Opt.c_cflag |= PARENB;      //enable parity
            Opt.c_cflag |= PARODD;      //奇校验
            Opt.c_iflag |= INPCK;       //disable parity checking
            break;
        }
        case 'e':
        case 'E':
        {
            Opt.c_cflag |= PARENB;      //enable parity
            Opt.c_cflag &amp;= ~PARODD;     //偶校验
            Opt.c_iflag |= INPCK;       //disable parity checking
            break;
        }
        case 's':
        case 'S':
        {
            Opt.c_cflag &amp;= ~PARENB;     //清除校验位
            Opt.c_cflag &amp;= ~CSTOPB;     //?????
            Opt.c_iflag |= INPCK;       //disable parity checking
            break;
        }
        default:
        {
            fprintf(stderr,&quot;Unsupoort parity.\n&quot;);
            return FALSE;
        }
    }
    switch (stopbits)                   //设置停止位
    {
        case 1:
        {
            Opt.c_cflag &amp;= ~CSTOPB;
            break;
        }
        case 2:
        {
            Opt.c_cflag |= CSTOPB;
            break;
        }
        default:
        {
            fprintf(stderr, &quot;Unsupport stopbits.\n&quot;);
            return FALSE;
        }
    }

    Opt.c_cflag |= (CLOCAL | CREAD);
    Opt.c_lflag &amp;= ~(ICANON | ECHO | ECHOE | ISIG);

    Opt.c_oflag &amp;= ~OPOST;
    Opt.c_oflag &amp;= ~(ONLCR | OCRNL);        //添加的

    Opt.c_iflag &amp;= ~(ICRNL | INLCR);
    Opt.c_iflag &amp;= ~(IXON | IXOFF | IXANY); //添加的

    tcflush(fd, TCIFLUSH);
    Opt.c_cc[VTIME] = 0;                    //设置超时为15sec
    Opt.c_cc[VMIN] = 0;                     //Update the Opt and do it now
    if (tcsetattr(fd, TCSANOW, &amp;Opt) != 0)
    {
        perror(&quot;tcsetattr fd&quot;);
        return FALSE;
    }
    return TRUE;
}

int main()
{
    int fd;
    int i, len, n=0;
    char read_buf[256];
    char write_buf[256];
    char c;
    struct termios opt;

    fd = open(SERIAL, O_RDWR|O_NOCTTY);
    if (fd == -1)
    {
        perror(&quot;open serial\n&quot;);
        exit(-1);
    }
    SetSpeed(fd, 115200);
    SetParity(fd, 8, 1, 'n');
    while (1)
    {
        n = 0;
        len = 0;
        memset(read_buf, 0, sizeof(read_buf));
        memset(write_buf, 0, sizeof(write_buf));

        while ((n=read(fd, read_buf, sizeof(read_buf))) &gt; 0)
        {
            read_buf[n] = '&#92;&#48;';
            printf(&quot;%s&quot;, read_buf);
        }
        scanf(&quot;%c&quot;, &amp;c);
        write(fd, &amp;c, 1);
        while ((n=read(fd, read_buf, sizeof(read_buf))) &gt; 0)
        {
            read_buf[n] = '&#92;&#48;';
            printf(&quot;%s\n&quot;, read_buf);
        }
    }
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.xefan.com/archives/83757.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TQ2440 串口程序</title>
		<link>http://www.xefan.com/archives/83741.html</link>
		<comments>http://www.xefan.com/archives/83741.html#comments</comments>
		<pubDate>Mon, 14 May 2012 08:10:01 +0000</pubDate>
		<dc:creator>龍昌</dc:creator>
				<category><![CDATA[嵌入式栏目]]></category>
		<category><![CDATA[ARM]]></category>
		<category><![CDATA[TQ2440]]></category>

		<guid isPermaLink="false">http://www.xefan.com/?p=83741</guid>
		<description><![CDATA[S3C2440的UART只需要3根线就可以实现通信功能，除去GND外只有两根线：一根发送TXD，一根接收RXD。 对于UART0,TXD0与GPH2是复用的，RXD0与GPH3是复用的。 因此使用UART0先要设置GPH2、GPH3： GPHCON &#38;= ~((3&#60;&#60;4)&#124;(3&#60;&#60;6)); GPHCON &#124;= (2&#60;&#60;4)&#124;(2&#60;&#60;6); 其次进行初始化。 与UART相关的寄存器： ULCONn：主要用于设置数据长度、停止位和检验位。 UCONn：主要用于设置数据发送和接收的模式，中断方式还是查询方式。 UBRDIVn：主要用于设置波特率。 UTRSTATn：包含发送和接收是否完成的状态位。 URXHn：接收数据缓冲寄存器，8位数据长度。 UTXHn：发送数据缓冲寄存器，8位数据长度。 例子程序下载： http://download.csdn.net/detail/wosuopu/4300998]]></description>
			<content:encoded><![CDATA[<p>S3C2440的UART只需要3根线就可以实现通信功能，除去GND外只有两根线：一根发送TXD，一根接收RXD。<br />
对于UART0,TXD0与GPH2是复用的，RXD0与GPH3是复用的。<br />
因此使用UART0先要设置GPH2、GPH3：<br />
GPHCON &amp;= ~((3&lt;&lt;4)|(3&lt;&lt;6));<br />
GPHCON |= (2&lt;&lt;4)|(2&lt;&lt;6);<br />
其次进行初始化。<br />
与UART相关的寄存器：<br />
ULCONn：主要用于设置数据长度、停止位和检验位。<br />
UCONn：主要用于设置数据发送和接收的模式，中断方式还是查询方式。<br />
UBRDIVn：主要用于设置波特率。<br />
UTRSTATn：包含发送和接收是否完成的状态位。<br />
URXHn：接收数据缓冲寄存器，8位数据长度。<br />
UTXHn：发送数据缓冲寄存器，8位数据长度。</p>
<p>例子程序下载：</p>
<p>http://download.csdn.net/detail/wosuopu/4300998</p>
]]></content:encoded>
			<wfw:commentRss>http://www.xefan.com/archives/83741.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TQ2440 定时器程序</title>
		<link>http://www.xefan.com/archives/83739.html</link>
		<comments>http://www.xefan.com/archives/83739.html#comments</comments>
		<pubDate>Sun, 13 May 2012 08:07:00 +0000</pubDate>
		<dc:creator>龍昌</dc:creator>
				<category><![CDATA[嵌入式栏目]]></category>
		<category><![CDATA[ARM]]></category>
		<category><![CDATA[TQ2440]]></category>

		<guid isPermaLink="false">http://www.xefan.com/?p=83739</guid>
		<description><![CDATA[S3C2440有两个PLL：MPLL（用于CPU及其他外设）、UPLL（专用于USB设备） MPLL会产生三个部分的时钟频率：FCLK、HCLK、PCLK S3C2440有5个16位定时器。定时器0和1共享一个8位预分频器，定时器2、3、4共享另一个8位预分频器。 定时器的时钟源为PCLK，首先经过预分频器降低频率后，进入第二分频。可生成5种不同的分频信号（1/2,1/4,1/8,1/16和TCLK）。 定时器启动后，TCNTn开始减一计数，当TCNTn等于TCMPn时TOUTn反转，TCNTn继续减数。当TCNTn=0时，TOUTn再反转，并触发中断（中断已使能）。若TCON设为自动加载，TCNTn/TCMPn值被重载。 与定时器相关的寄存器： TCFG0：配置两个8位预分频器［15:8］决定定时器2,3,4的预标定器值，[7:0]决定定时器0,1。 输出频率=PCLK/(prescaler value+1) TCFG1：设置第二个分频，可设置5种不同分频信号（1/2,1/4,1/8,1/16,TCLK） 定时器工作频率=PCLK/(Prescaler value+1)/(divider value) divider value=2,4,8,16 Prescaler=0~255 TCON：定时器控制寄存器 TCNTBn：设置一个被装载到递减计数器中的初始值 TCMPBn：设置一个被装载到比较寄存器中用来和递减计数器的值比较的初始值 TCNTOn：通过读取其可以得到TCNTn的值 TCNTB=(PCLK/(Prescaler+1)/divider)*中断间隔 定时器初始化例子： TCFG0 = 99; //预分频器0=99 TCFG1 = 0&#215;03; //选择16分频 TCNTB0 = 31250; //0.5秒触发一次中断 TCON &#124;= (1&#60; TCON = 0&#215;09; &#8230; <a href="http://www.xefan.com/archives/83739.html">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>S3C2440有两个PLL：MPLL（用于CPU及其他外设）、UPLL（专用于USB设备）<br />
MPLL会产生三个部分的时钟频率：FCLK、HCLK、PCLK</p>
<p>S3C2440有5个16位定时器。定时器0和1共享一个8位预分频器，定时器2、3、4共享另一个8位预分频器。</p>
<p>定时器的时钟源为PCLK，首先经过预分频器降低频率后，进入第二分频。可生成5种不同的分频信号（1/2,1/4,1/8,1/16和TCLK）。</p>
<p>定时器启动后，TCNTn开始减一计数，当TCNTn等于TCMPn时TOUTn反转，TCNTn继续减数。当TCNTn=0时，TOUTn再反转，并触发中断（中断已使能）。若TCON设为自动加载，TCNTn/TCMPn值被重载。</p>
<p>与定时器相关的寄存器：<br />
TCFG0：配置两个8位预分频器［15:8］决定定时器2,3,4的预标定器值，[7:0]决定定时器0,1。<br />
输出频率=PCLK/(prescaler value+1)</p>
<p>TCFG1：设置第二个分频，可设置5种不同分频信号（1/2,1/4,1/8,1/16,TCLK）<br />
定时器工作频率=PCLK/(Prescaler value+1)/(divider value)<br />
divider value=2,4,8,16<br />
Prescaler=0~255</p>
<p>TCON：定时器控制寄存器<br />
TCNTBn：设置一个被装载到递减计数器中的初始值<br />
TCMPBn：设置一个被装载到比较寄存器中用来和递减计数器的值比较的初始值<br />
TCNTOn：通过读取其可以得到TCNTn的值<br />
TCNTB=(PCLK/(Prescaler+1)/divider)*中断间隔</p>
<p>定时器初始化例子：<br />
TCFG0 = 99; //预分频器0=99<br />
TCFG1 = 0&#215;03; //选择16分频<br />
TCNTB0 = 31250; //0.5秒触发一次中断<br />
TCON |= (1&lt; TCON = 0&#215;09; //自动加载，清“手动更新”，启动定时器0</p>
<p>一个简单的定时器程序下载：http://download.csdn.net/detail/wosuopu/4298320</p>
]]></content:encoded>
			<wfw:commentRss>http://www.xefan.com/archives/83739.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TQ2440 蜂鸣器程序</title>
		<link>http://www.xefan.com/archives/83736.html</link>
		<comments>http://www.xefan.com/archives/83736.html#comments</comments>
		<pubDate>Sat, 12 May 2012 15:07:45 +0000</pubDate>
		<dc:creator>龍昌</dc:creator>
				<category><![CDATA[嵌入式栏目]]></category>
		<category><![CDATA[ARM]]></category>
		<category><![CDATA[TQ2440]]></category>

		<guid isPermaLink="false">http://www.xefan.com/?p=83736</guid>
		<description><![CDATA[根据原理图知道TOUT0与GPB0连接，因此当GPB0输出高电平时蜂鸣器鸣；当GPB0输出低电平时蜂鸣器停止鸣。 程序如下： 文件名 beep.S 文件名 gpio.inc 文件名 Makefile]]></description>
			<content:encoded><![CDATA[<p>根据原理图知道TOUT0与GPB0连接，因此当GPB0输出高电平时蜂鸣器鸣；当GPB0输出低电平时蜂鸣器停止鸣。<br />
程序如下：<br />
文件名 beep.S</p>
<pre class="brush: plain; title: ; notranslate">
.include &quot;gpio.inc&quot;
.text
.global _start
_start:
        ldr r0, =GPBCON
        mov r1, #0b01
        str r1, [r0]
        ldr r0, =GPBUP
        mov r1, #0
        str r1, [r0]
        ldr r0, =GPBDAT
        mov r1, #1
next:
        mvn r1, r1
        str r1, [r0]
        bl delay
        b next

delay:
        ldr r4, =100000
delay1: sub r4, r4, #1
        cmp r4, #0
        bgt delay1
        mov pc, lr

main_loop:
        b main_loop
</pre>
<p>文件名 gpio.inc</p>
<pre class="brush: plain; title: ; notranslate">

.equ GPACON, 0x56000000
.equ GPADAT, 0x56000004

.equ GPBCON, 0x56000010
.equ GPBDAT, 0x56000014
.equ GPBUP,  0x56000018

.equ GPCCON, 0x56000020
.equ GPCDAT, 0x56000024
.equ GPCUP,  0x56000028

.equ GPDCON, 0x56000030
.equ GPDDAT, 0x56000034
.equ GPDUP,  0x56000038

.equ GPECON, 0x56000040
.equ GPEDAT, 0x56000044
.equ GPEUP,  0x56000048

.equ GPFCON, 0x56000050
.equ GPFDAT, 0x56000054
.equ GPFUP,  0x56000058

.equ GPGCON, 0x56000060
.equ GPGDAT, 0x56000064
.equ GPGUP,  0x56000068

.equ GPHCON, 0x56000070
.equ GPHDAT, 0x56000074
.equ GPHUP,  0x56000078

.equ GPJCON, 0x560000d0
.equ GPJDAT, 0x560000d4
.equ GPJUP,  0x560000d8
</pre>
<p>文件名 Makefile</p>
<pre class="brush: plain; title: ; notranslate">

ARCH = arm-linux-
CC = $(ARCH)gcc
LD = $(ARCH)ld
OBJCOPY = $(ARCH)objcopy

all:beep.S
	$(CC) -g -c -o beep.o beep.S
	$(LD) -Ttext 0x00000000 -g -o beep-elf beep.o
	$(OBJCOPY) -O binary -S beep-elf beep.bin

clean:
	rm -f beep.o beep-elf beep.bin
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.xefan.com/archives/83736.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TQ2440 按键裸机驱动</title>
		<link>http://www.xefan.com/archives/83731.html</link>
		<comments>http://www.xefan.com/archives/83731.html#comments</comments>
		<pubDate>Thu, 10 May 2012 12:55:41 +0000</pubDate>
		<dc:creator>龍昌</dc:creator>
				<category><![CDATA[嵌入式栏目]]></category>
		<category><![CDATA[ARM]]></category>
		<category><![CDATA[TQ2440]]></category>

		<guid isPermaLink="false">http://www.xefan.com/?p=83731</guid>
		<description><![CDATA[根据TQ2440的手册可知KEY1、2、3、4分别由GPF1、4、2、0控制。 程序的步骤为： 1、先将GPB1、4、2、0设为输入； 2、若有按键按下则对应引脚为0，否则为1. 程序如下： 文件名 crt0.S 文件名 gpio.h 文件名 key.c 文件名 Makefile]]></description>
			<content:encoded><![CDATA[<p>根据TQ2440的手册可知KEY1、2、3、4分别由GPF1、4、2、0控制。<br />
程序的步骤为：<br />
1、先将GPB1、4、2、0设为输入；<br />
2、若有按键按下则对应引脚为0，否则为1.<br />
程序如下：<br />
文件名 crt0.S</p>
<pre class="brush: plain; title: ; notranslate">
.text
.global _start
_start:
        ldr r0, =0x56000010 @WATCHDOG
        mov r1, #0
        str r1, [r0]
        ldr sp, =1024*4
        bl main

halt_loop:
        b halt_loop
</pre>
<p>文件名 gpio.h</p>
<pre class="brush: cpp; title: ; notranslate">

#ifndef _GPIO_H
#define _GPIO_H

#define GPACON (*(volatile unsigned int*)0x56000000)
#define GPADAT (*(volatile unsigned int*)0x56000004)

#define GPBCON (*(volatile unsigned int*)0x56000010)
#define GPBDAT (*(volatile unsigned int*)0x56000014)
#define GPBUP  (*(volatile unsigned int*)0x56000018)

#define GPCCON (*(volatile unsigned int*)0x56000020)
#define GPCDAT (*(volatile unsigned int*)0x56000024)
#define GPCUP  (*(volatile unsigned int*)0x56000028)

#define GPDCON (*(volatile unsigned int*)0x56000030)
#define GPDDAT (*(volatile unsigned int*)0x56000034)
#define GPDUP  (*(volatile unsigned int*)0x56000038)

#define GPECON (*(volatile unsigned int*)0x56000040)
#define GPEDAT (*(volatile unsigned int*)0x56000044)
#define GPEUP  (*(volatile unsigned int*)0x56000048)

#define GPFCON (*(volatile unsigned int*)0x56000050)
#define GPFDAT (*(volatile unsigned int*)0x56000054)
#define GPFUP  (*(volatile unsigned int*)0x56000058)

#define GPGCON (*(volatile unsigned int*)0x56000060)
#define GPGDAT (*(volatile unsigned int*)0x56000064)
#define GPGUP  (*(volatile unsigned int*)0x56000068)

#define GPHCON (*(volatile unsigned int*)0x56000070)
#define GPHDAT (*(volatile unsigned int*)0x56000074)
#define GPHUP  (*(volatile unsigned int*)0x56000078)

#define GPJCON (*(volatile unsigned int*)0x560000d0)
#define GPJDAT (*(volatile unsigned int*)0x560000d4)
#define GPJUP  (*(volatile unsigned int*)0x560000d8)

#endif
</pre>
<p>文件名 key.c</p>
<pre class="brush: cpp; title: ; notranslate">

#include &quot;gpio.h&quot;

void delay()
{
    int i;
    for (i=0; i&lt;100000; i++);
}

void main()
{
    GPFCON = 0b0011000000;
    GPFDAT = 0b10111;

    GPBCON = (0b01010101&lt;&lt;10);
    GPBDAT = 0b111100000;
    while(1)
    {
        if((GPFDAT &amp; 0b10) == 0)                   //key1
        {
            GPBDAT = 0b111000000;
        }
        else if((GPFDAT &amp; 0b10000) == 0)        //key2
        {
            GPBDAT = 0b110100000;
        }
        else if((GPFDAT &amp; 0b100) == 0)          //key3
        {
            GPBDAT = 0b101100000;
        }
        else if((GPFDAT &amp; 0b1) == 0)            //key4
        {
            GPBDAT = 0b011100000;
        }
        else continue;
        delay();
        GPBDAT = 0b111100000;
    }
}
</pre>
<p>文件名 Makefile</p>
<pre class="brush: plain; title: ; notranslate">

ARCH = arm-linux-
CC = $(ARCH)gcc
LD = $(ARCH)ld
OBJDUMP = $(ARCH)objdump
OBJCOPY = $(ARCH)objcopy

all: crt0.S key.c
	$(CC) -nostdlib -g -c -o crt0.o crt0.S
	$(CC) -nostdlib -g -c -o key.o key.c
	$(LD) -Ttext 0x00000000 -g crt0.o key.o -o key-elf
	$(OBJCOPY) -O binary -S key-elf key_c.bin
	$(OBJDUMP) -D -m arm key-elf &gt; key.dis

clean:
	rm -f *.o key-elf key_c.bin key.dis
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.xefan.com/archives/83731.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TQ2440 LED裸机驱动</title>
		<link>http://www.xefan.com/archives/83725.html</link>
		<comments>http://www.xefan.com/archives/83725.html#comments</comments>
		<pubDate>Sun, 29 Apr 2012 12:26:34 +0000</pubDate>
		<dc:creator>龍昌</dc:creator>
				<category><![CDATA[嵌入式栏目]]></category>
		<category><![CDATA[ARM]]></category>
		<category><![CDATA[TQ2440]]></category>

		<guid isPermaLink="false">http://www.xefan.com/?p=83725</guid>
		<description><![CDATA[根据TQ2440的手册可知LED1、2、3、4分别由GPB5、6、7、8控制。 程序的步骤为： 1、先将GPB5、6、7、8设为输出； 2、将对应位置0表示LED灯亮，对应位置1表示灯灭。 程序如下： Makefile内容如下：]]></description>
			<content:encoded><![CDATA[<p>根据TQ2440的手册可知LED1、2、3、4分别由GPB5、6、7、8控制。<br />
程序的步骤为：<br />
1、先将GPB5、6、7、8设为输出；<br />
2、将对应位置0表示LED灯亮，对应位置1表示灯灭。</p>
<p>程序如下：</p>
<pre class="brush: plain; title: ; notranslate">
@  文件名：led_on.s
.equ GPBCON, 0x56000010
.equ GPBDAT, 0x56000014
.equ GPBUP,  0x56000018

.text
.global _start
_start:
    LDR R0,=GPBCON
    MOV R1,#0b010101010000000000    @将GPB5、6、7、8设为输出
    STR R1,[R0]
    LDR R0,=GPBDAT
    MOV R1,#0x00000000
n:  MVN R1,R1
    STR R1,[R0]
    LDR R2,=100000
w:  SUB R2,R2,#1
    CMP R2,#0
    BGT w
    B n

MAIN_LOOP:
    B MAIN_LOOP
.end
</pre>
<p>Makefile内容如下：</p>
<pre class="brush: plain; title: ; notranslate">
ARCH=arm-linux-
CC=$(ARCH)gcc
LD=$(ARCH)ld
Objcopy=$(ARCH)objcopy

led_on:led_on.s
	$(CC) -g -c -o led_on.o led_on.s
	$(LD) -Ttext 0x00000000 -g led_on.o -o led_on_elf
	$(Objcopy) -O binary -S led_on_elf led_on.bin
clean:
	rm -f led_on.bin
	rm -f led_on.o
	rm -f led_on_elf
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.xefan.com/archives/83725.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PyGTK TreeView的一些心得</title>
		<link>http://www.xefan.com/archives/83722.html</link>
		<comments>http://www.xefan.com/archives/83722.html#comments</comments>
		<pubDate>Sun, 15 Apr 2012 14:05:47 +0000</pubDate>
		<dc:creator>龍昌</dc:creator>
				<category><![CDATA[Python栏目]]></category>
		<category><![CDATA[gtk]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.xefan.com/?p=83722</guid>
		<description><![CDATA[TreeView是属于MVC(Model/View/Control）模式的。 所需要的构件有： TreeView -树视图，用于显示数据 TreeViewColumn -视图的列 CellRenderer -渲染器，用于控制数据的显示效果 TreeModel/ListModel -树模式（树状/列表），用于保存数据 创建一个TreeView的步骤： 1、创建一个模式，TreeModel或ListModel； 2、向模式中添加数据； 3、创建视图TreeView，并添加之前创建的模式； 4、创建列TreeViewColumn,并添加视图TreeView中； 5、创建渲染器CellRenderer，并添加到列TreeViewColumn中； 6、设置行选择信号函数和渲染器操作信号函数。 其中GTK提供的渲染器有CellRendererAccel、CellRendererCombo、CellRendererPixbuf、CellRendererProgress、CellRendererSpin、CellRendererSpinner、CellRendererText、CellRendererToggle 8种 这里有个例子介绍了这几种渲染器的用法，可以参考下再举一反三： https://gist.github.com/2389339]]></description>
			<content:encoded><![CDATA[<p>TreeView是属于MVC(Model/View/Control）模式的。<br />
所需要的构件有：<br />
TreeView             -树视图，用于显示数据<br />
TreeViewColumn       -视图的列<br />
CellRenderer         -渲染器，用于控制数据的显示效果<br />
TreeModel/ListModel  -树模式（树状/列表），用于保存数据</p>
<p>创建一个TreeView的步骤：<br />
1、创建一个模式，TreeModel或ListModel；<br />
2、向模式中添加数据；<br />
3、创建视图TreeView，并添加之前创建的模式；<br />
4、创建列TreeViewColumn,并添加视图TreeView中；<br />
5、创建渲染器CellRenderer，并添加到列TreeViewColumn中；<br />
6、设置行选择信号函数和渲染器操作信号函数。</p>
<p>其中GTK提供的渲染器有CellRendererAccel、CellRendererCombo、CellRendererPixbuf、CellRendererProgress、CellRendererSpin、CellRendererSpinner、CellRendererText、CellRendererToggle 8种</p>
<p>这里有个例子介绍了这几种渲染器的用法，可以参考下再举一反三：</p>
<p>https://gist.github.com/2389339</p>
]]></content:encoded>
			<wfw:commentRss>http://www.xefan.com/archives/83722.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>将PIL的Image类型转化为pygtk的Image类型</title>
		<link>http://www.xefan.com/archives/83718.html</link>
		<comments>http://www.xefan.com/archives/83718.html#comments</comments>
		<pubDate>Sat, 14 Apr 2012 11:44:02 +0000</pubDate>
		<dc:creator>龍昌</dc:creator>
				<category><![CDATA[Python栏目]]></category>
		<category><![CDATA[gtk]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.xefan.com/?p=83718</guid>
		<description><![CDATA[Python代码如下：]]></description>
			<content:encoded><![CDATA[<p>Python代码如下：</p>
<pre class="brush: python; title: ; notranslate">
# PIL的Image类型转化为gtk的Image类型
import gtk
import StringIO

f = StringIO.StringIO()
#im为PIL的Image类型
im.save(f, &quot;ppm&quot;)
contents = f.getvalue()
f.close()
loader = gtk.gdk.PixbufLoader(&quot;pnm&quot;)
loader.write(contents, len(contents))
pixbuf = loader.get_pixbuf()
loader.close()
i = gtk.Image()
i.set_from_pixbuf(pixbuf)
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.xefan.com/archives/83718.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>使用Python打印日历</title>
		<link>http://www.xefan.com/archives/83714.html</link>
		<comments>http://www.xefan.com/archives/83714.html#comments</comments>
		<pubDate>Fri, 13 Apr 2012 07:22:08 +0000</pubDate>
		<dc:creator>龍昌</dc:creator>
				<category><![CDATA[Python栏目]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.xefan.com/?p=83714</guid>
		<description><![CDATA[基姆拉尔森计算公式 W= (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400) mod 7 在公式中d表示日期中的日数+1，m表示月份数，y表示年数。 注意：在公式中有个与其他公式不同的地方： 把一月和二月看成是上一年的十三月和十四月，例：如果是2004-1-10则换算成：2003-13-10来代入公式计算。]]></description>
			<content:encoded><![CDATA[<p>基姆拉尔森计算公式<br />
W= (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400) mod 7<br />
在公式中d表示日期中的日数+1，m表示月份数，y表示年数。<br />
注意：在公式中有个与其他公式不同的地方：<br />
把一月和二月看成是上一年的十三月和十四月，例：如果是2004-1-10则换算成：2003-13-10来代入公式计算。</p>
<pre class="brush: python; title: ; notranslate">

#!/usr/bin/env python
#-*- coding:utf-8 -*-
##
# @文件名(file): date.py
# @作者(author): 龙昌锦(LongChangjin)
# @博客(blog): http://www.xefan.com
# @时间(date): 2012-04-13
# 

monthday = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
weekname = [&quot;星期日&quot;,&quot;星期一&quot;,&quot;星期二&quot;,&quot;星期三&quot;,&quot;星期四&quot;,&quot;星期五&quot;,&quot;星期六&quot;]
# 计算某年某月某日是星期几
# 基姆拉尔森计算公式
def week(y, m, d):
    if m == 1 or m == 2:
        m = m + 12
        y = y - 1
    w = ((d + 2 * m + 3 * (m+1) / 5 + y + y/4 - y/100 + y/400) + 1) % 7
    return int(w)

year, month = input(&quot;输入日期，如：2012,4:&quot;)
if year%4 == 0:
    monthday[1] = 29
w = week(year, month, 1)

print(&quot;%d年%d月&quot; % (year, month))
print weekname[0], weekname[1], weekname[2], weekname[3], weekname[4], weekname[5], weekname[6]
i = 0
while i &lt; w:
    print(&quot;      &quot;),
    i = i + 1
i = 1
while i &lt;= monthday[month-1]:
    print(&quot;%3d   &quot; % i),
    i = i + 1
    w = w + 1
    if w == 7:
        print(&quot;&quot;)
        w = 0

#运行结果如下：
#[lcj@lcj time]$ python date.py
#输入日期，如：2012,4:2012,2
#2012年2月
#星期日 星期一 星期二 星期三 星期四 星期五 星期六
#                       1      2      3      4
#  5      6      7      8      9     10     11
# 12     13     14     15     16     17     18
# 19     20     21     22     23     24     25
# 26     27     28     29
#[lcj@lcj time]$
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.xefan.com/archives/83714.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>u-Boot使用nfs根文件系统</title>
		<link>http://www.xefan.com/archives/83710.html</link>
		<comments>http://www.xefan.com/archives/83710.html#comments</comments>
		<pubDate>Fri, 16 Mar 2012 07:02:34 +0000</pubDate>
		<dc:creator>龍昌</dc:creator>
				<category><![CDATA[嵌入式栏目]]></category>
		<category><![CDATA[Arch]]></category>
		<category><![CDATA[ARM]]></category>

		<guid isPermaLink="false">http://www.xefan.com/?p=83710</guid>
		<description><![CDATA[使用nfs根文件系统对于开发非常方便，不用每次编译好后又要烧写到开发板上。 设置方法： 打开开发板电源后进入u-boot，然后选择“[0] Set the boot parameters”。 再选择“[1] Set NFS boot parameter ”。 然后依次输入PC的IP、开发板的IP、子网掩码、NFS目录。 例子如下： Enter the PC IP address:(xxx.xxx.xxx.xxx) 10.10.10.2 Enter the SKY2440/TQ2440 IP address:(xxx.xxx.xxx.xxx) 10.10.10.3 Enter the Mask IP address:(xxx.xxx.xxx.xxx) 255.255.255.0 Enter NFS directory:(eg: /opt/EmbedSky/root_nfs) /opt/EmbedSky/root bootargs: console=ttySAC0 &#8230; <a href="http://www.xefan.com/archives/83710.html">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>使用nfs根文件系统对于开发非常方便，不用每次编译好后又要烧写到开发板上。</p>
<p>设置方法：<br />
打开开发板电源后进入u-boot，然后选择“[0] Set the boot parameters”。<br />
再选择“[1] Set NFS boot parameter ”。<br />
然后依次输入PC的IP、开发板的IP、子网掩码、NFS目录。<br />
例子如下：<br />
Enter the PC IP address:(xxx.xxx.xxx.xxx)<br />
10.10.10.2<br />
Enter the SKY2440/TQ2440 IP address:(xxx.xxx.xxx.xxx)<br />
10.10.10.3<br />
Enter the Mask IP address:(xxx.xxx.xxx.xxx)<br />
255.255.255.0<br />
Enter NFS directory:(eg: /opt/EmbedSky/root_nfs)<br />
/opt/EmbedSky/root<br />
bootargs: console=ttySAC0 root=/dev/nfs nfsroot=10.10.10.2:/opt/EmbedSky/root ip=10.10.10.3:10.10.10.2:10.10.10.3:255.255.255.0:SKY2440.embedsky.net:eth0:off</p>
<p>输入好后再选择“[s] Save the parameters to Nand Flash”保存设置即可。</p>
<p>以上是一般情况，下面再说说我的特殊情况。</p>
<p>=====================分割线===============================<br />
我在PC上安装的是ArchLinux，按照以上方法运行时挂载失败，提示Root-NFS: Server returned error -93 while mounting /opt/EmbedSky/root<br />
－93的意思好像是没有这个协议。</p>
<p>于是我又在虚拟机里安装了ubuntu，再尝试以上方法结果却成功了。<br />
最后我查了资料，原因好像是u-boot使用的nfs3，而ArchLinux的官网上说nfs3太老了所以Arch用的是nfs4。因此就出现了这个问题。<br />
解决方法：添加一个”,v3&#8243;参数。如：<br />
Enter NFS directory:(eg: /opt/EmbedSky/root_nfs)<br />
/opt/EmbedSky/root<span style="color: #ff0000;">,v3</span><br />
bootargs: console=ttySAC0 root=/dev/nfs nfsroot=10.10.10.2:/opt/EmbedSky/root<span style="color: #ff0000;">,v3</span> ip=10.10.10.3:10.10.10.2:10.10.10.3:255.255.255.0:SKY2440.embedsky.net:eth0:off</p>
]]></content:encoded>
			<wfw:commentRss>http://www.xefan.com/archives/83710.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Git常用命令</title>
		<link>http://www.xefan.com/archives/83706.html</link>
		<comments>http://www.xefan.com/archives/83706.html#comments</comments>
		<pubDate>Tue, 13 Mar 2012 03:04:03 +0000</pubDate>
		<dc:creator>龍昌</dc:creator>
				<category><![CDATA[编程开发]]></category>
		<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://www.xefan.com/?p=83706</guid>
		<description><![CDATA[最近正在看Git，做个笔记，把常用的命令记下。 git init 初始化 git add &#60;file&#62; 将file添加到跟踪 git commit -m “..” 将修改提交到库，备注为”&#8230;” git commit -a -m “&#8230;” 将所有跟踪文件全部提交 git status 查看状态 git rm &#60;file&#62; 移除文件，之后再commit提交 git mv &#60;file1&#62; &#60;file2&#62; 移动文件，之后再commit提交 git log 查看记录 git commit —amend 修改最后一次提交 git remote &#8230; <a href="http://www.xefan.com/archives/83706.html">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>最近正在看Git，做个笔记，把常用的命令记下。</p>
<p>git init 初始化<br />
git add &lt;file&gt; 将file添加到跟踪<br />
git commit -m “..” 将修改提交到库，备注为”&#8230;”<br />
git commit -a -m “&#8230;” 将所有跟踪文件全部提交<br />
git status 查看状态<br />
git rm &lt;file&gt; 移除文件，之后再commit提交<br />
git mv &lt;file1&gt; &lt;file2&gt; 移动文件，之后再commit提交</p>
<p>git log 查看记录<br />
git commit —amend 修改最后一次提交<br />
git remote -v 查看远程仓库，-v显示地址<br />
git remote add &lt;shortname&gt; &lt;url&gt; 添加远程仓库，别名为shortname<br />
git fetch &lt;remote-name&gt; 从远程仓库抓取数据<br />
git push &lt;remote-name&gt; &lt;branch&gt; 从本地branch推送到远程remote</p>
<p>git tag 显示所有标签<br />
git tag -l &lt;reg&gt; 按照reg表达式来搜索标签<br />
git tag -a &lt;name&gt; -m “..” 创建标签<br />
git tag -a &lt;name&gt; &lt;hash&gt; 为某次提交打标签<br />
git push remote —tags 推送本地所有标签</p>
<p>git branch &lt;name&gt; 从当前分支新建一个分支<br />
git checkout &lt;name&gt; 切换到name分支<br />
git checkout -b &lt;name&gt; 新建并切换到name分支<br />
Gti merge &lt;name&gt; 将name分支合并到当前分支<br />
git branch -d &lt;name&gt; 删除name分支<br />
git branch -v 查看各分支最后一次提交</p>
<p>git fetch &lt;remote-name&gt; 从远程分支获取数据<br />
git push &lt;remote&gt; [localbranch]:[remotebranch] 推送本地localbran到远程remotebranch，若localbranch参数为空则删除远程remotebranch分支<br />
git chekcout -b &lt;branch&gt; &lt;remote/branch&gt; 从远程分支分化出一个新本地分支</p>
<p>git stash 暂存不想提交的修改<br />
git stash list 查看暂存列表<br />
git stash apply &lt;stash-name&gt; 应用暂存</p>
<p>git checkout —set-upstream &lt;localbranch&gt; &lt;remote/branch&gt; 本地分支localbranch跟踪远程分支branch<br />
git clone &lt;url&gt; 克隆远程项目</p>
<p>git submodule add &lt;url&gt; &lt;name&gt; 创建子模块，保存到name目录<br />
git submodule init 初始化子模块<br />
git submodule update 从远程下载更新子模块</p>
<p>git archive [--format==tar|zip] [--prefix=&lt;prefix&gt;/] [-o file] &lt;commit&gt; [&lt;path&gt;...] 将commit提交记录中的path目录下的文件以format格式打包导出到file<br />
git revert HEAD^ 撤消前前一次提交<br />
git revert &lt;hash&gt; 撤消指定的版本<br />
git revert —hard &lt;commit&gt; 彻底回退到某个版本</p>
]]></content:encoded>
			<wfw:commentRss>http://www.xefan.com/archives/83706.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linux进程通信——使用消息队列</title>
		<link>http://www.xefan.com/archives/83703.html</link>
		<comments>http://www.xefan.com/archives/83703.html#comments</comments>
		<pubDate>Fri, 24 Feb 2012 11:06:58 +0000</pubDate>
		<dc:creator>龍昌</dc:creator>
				<category><![CDATA[编程开发]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.xefan.com/?p=83703</guid>
		<description><![CDATA[头文件： #include &#60;sys/ipc.h&#62; #include &#60;sys/msg.h&#62; #include &#60;sys/types.h&#62; 函数： key_t ftok(const char *filename, int proj_id); 通过文件名和项目号获得System V IPC键值（用于创建消息队列、共享内存所用） proj_id：项目号，不为0即可 返回：成功则返回键值，失败则返回-1 函数： int msgget(key_t key, int msgflg)； key：键值，当为IPC_PRIVATE时新建一块共享内存； shmflg：标志。 IPC_CREAT：内存不存在则新建，否则打开； IPC_EXCL：只有在内存不存在时才创建，否则出错。 返回：成功则返回标识符，出错返回-1 函数： int msgsnd(int msgid, const void *msgp, size_t sz, int &#8230; <a href="http://www.xefan.com/archives/83703.html">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>头文件： #include &lt;sys/ipc.h&gt;<br />
#include &lt;sys/msg.h&gt;<br />
#include &lt;sys/types.h&gt;</p>
<p>函数： key_t ftok(const char *filename, int proj_id);<br />
通过文件名和项目号获得System V IPC键值（用于创建消息队列、共享内存所用）<br />
proj_id：项目号，不为0即可<br />
返回：成功则返回键值，失败则返回-1</p>
<p>函数： int msgget(key_t key, int msgflg)；<br />
key：键值，当为IPC_PRIVATE时新建一块共享内存；<br />
shmflg：标志。<br />
IPC_CREAT：内存不存在则新建，否则打开；<br />
IPC_EXCL：只有在内存不存在时才创建，否则出错。<br />
返回：成功则返回标识符，出错返回-1</p>
<p>函数： int msgsnd(int msgid, const void *msgp, size_t sz, int flg)；<br />
向消息队列发送消息<br />
msgid：通过msgget获取<br />
msgp：指向消息内容的指针<br />
sz：消息内容的大小<br />
flg：处理方式；如为IPC_NOWAIT时表示空间不足时不会阻塞<br />
返回：成功则返回0，失败返回-1</p>
<p>函数： int msgrcv(int msgid, void *msgp, size_t sz, long type, int flg)；<br />
从消息队列读取消息<br />
msgid：通过msgget获取<br />
msgp：指向消息内容的指针<br />
sz：消息内容的大小<br />
type：指定接收的消息类型；若为0则队列第一条消息将被读取，而不管类型；若大于0则队列中同类型的消息将被读取，如在flg中设了MSG_RXCEPT位将读取指定类型的其他消息；若小于0读取绝对值小于type的消息。<br />
flg：处理方式；<br />
返回：成功返回收到消息长度，错误返回-1</p>
<p>函数： int msgctl(int msgid, int cmd, struct msgid_ds *buf)；<br />
msgid：通过msgget获取<br />
cmd：控制命令，如下：<br />
IPC_STAT：获取消息队列状态<br />
IPC_SET：改变消息队列状态<br />
IPC_RMID：删除消息队列<br />
buf：结构体指针，用于存放消息队列状态<br />
返回：成功返回与cmd相关的正数，错误返回-1</p>
<p><span style="color: #ff0000;">注意：消息队列一旦创建就会一直存在系统中，直到手动删除或者重启系统。可以使用ipcs -q命令来查看系统存在的消息队列。</span></p>
<p>例子：</p>
<pre class="brush: cpp; title: ; notranslate">
/****************************************
 *
 * 使用消息队列进行进程通信——写进程
 * 该进程用于创建信号量
 * 龙昌博客：http://www.xefan.com
 *
 ****************************************/
#include &lt;sys/types.h&gt;
#include &lt;sys/ipc.h&gt;
#include &lt;sys/msg.h&gt;
#include &lt;stdio.h&gt;

typedef struct _msg_buf{
    long type;          //消息类型
    char buf[100];      //消息内容
} msg_buf;

int main()
{
    int key, qid;
    msg_buf buf;
    key = ftok(&quot;tmp&quot;, 10);
    qid = msgget(key, IPC_CREAT);
    printf(&quot;key: %d\nqid: %d\n&quot;, key, qid);
    buf.type = 10;
    while (1)
    {
        fgets(buf.buf, 100, stdin);
        if (msgsnd(qid, (void *)&amp;buf, 100, 0) &lt; 0)
        {
            perror(&quot;msgsnd&quot;);
            exit(-1);
        }
    }
    return 0;
}
</pre>
<p>&nbsp;</p>
<pre class="brush: cpp; title: ; notranslate">
/****************************************
 *
 * 使用消息队列进行进程通信——读进程
 * 该进程用于创建信号量
 * 龙昌博客：http://www.xefan.com
 *
 ****************************************/
#include &lt;sys/types.h&gt;
#include &lt;sys/ipc.h&gt;
#include &lt;sys/msg.h&gt;
#include &lt;stdio.h&gt;

typedef struct _msg_buf{
    long type;          //消息类型
    char buf[100];      //消息内容
} msg_buf;

int main()
{
    int key, qid;
    msg_buf buf;
    key = ftok(&quot;tmp&quot;, 10);
    qid = msgget(key, IPC_CREAT);
    printf(&quot;key: %d\nqid: %d\n&quot;, key, qid);
    while (1)
    {
        if (msgrcv(qid, (void *)&amp;buf, 100, 0, 0) &lt; 0)
        {
            perror(&quot;msgrcv&quot;);
            exit(-1);
        }
        printf(&quot;type:%d\nget:%s\n&quot;, buf.type, buf.buf);
    }
    return 0;
}
</pre>
<p>先运行写进程再运行读进程。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.xefan.com/archives/83703.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linux进程通信——使用信号量</title>
		<link>http://www.xefan.com/archives/83700.html</link>
		<comments>http://www.xefan.com/archives/83700.html#comments</comments>
		<pubDate>Thu, 23 Feb 2012 01:49:23 +0000</pubDate>
		<dc:creator>龍昌</dc:creator>
				<category><![CDATA[编程开发]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.xefan.com/?p=83700</guid>
		<description><![CDATA[头文件： #include &#60;sys/ipc.h&#62; #include &#60;sys/sem.h&#62; #include &#60;sys/types.h&#62; 函数： key_t ftok(const char *filename, int proj_id); 通过文件名和项目号获得System V IPC键值（用于创建消息队列、共享内存所用） proj_id：项目号，不为0即可 返回：成功则返回键值，失败则返回-1 函数： int semget(key_t key, int nsems, int msgflg)； key：键值，当为IPC_PRIVATE时新建。 nsems：信号个数。 msgflg：标志。 IPC_CREAT：不存在则新建，否则打开； IPC_EXCL：与IPC_CREAT一同使用时，只有在不存在时才创建，否则出错。 返回：成功则返回IPC标识符，出错返回-1 函数： int semop(int semid, struct sembuf *sops, &#8230; <a href="http://www.xefan.com/archives/83700.html">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>头文件： #include &lt;sys/ipc.h&gt;<br />
#include &lt;sys/sem.h&gt;<br />
#include &lt;sys/types.h&gt;</p>
<p>函数： key_t ftok(const char *filename, int proj_id);<br />
通过文件名和项目号获得System V IPC键值（用于创建消息队列、共享内存所用）<br />
proj_id：项目号，不为0即可<br />
返回：成功则返回键值，失败则返回-1</p>
<p>函数： int semget(key_t key, int nsems, int msgflg)；<br />
key：键值，当为IPC_PRIVATE时新建。<br />
nsems：信号个数。<br />
msgflg：标志。<br />
IPC_CREAT：不存在则新建，否则打开；<br />
IPC_EXCL：与IPC_CREAT一同使用时，只有在不存在时才创建，否则出错。<br />
返回：成功则返回IPC标识符，出错返回-1</p>
<p>函数： int semop(int semid, struct sembuf *sops, unsigned nsops)；<br />
semid：通过semget获取<br />
sops：指向待操作的信号灯结构体，原型如下：<br />
struct sembuf{<br />
unsigned short sem_num; //信号灯编号，从0开始<br />
short sem_op; //为正数代表释放信号；为负代表获取信号<br />
Short sem_flg; //操作的标识；IPC_NOWAIT：不阻塞；IPC_UNDO：程序结束时释放信号量<br />
}<br />
nsops：要操作的信号量数<br />
返回：成功则返回共享内存起始地址，失败返回-1</p>
<p>函数： void semctl(int semid, int semnum, int cmd, union semun arg)；<br />
semid：通过semget获取<br />
semnum：操作的信号灯编号<br />
cmd：控制命令，如下：<br />
GETPID：获取sempid<br />
GETVAL：获取semval<br />
SETVAL：设置semval<br />
IPC_RMID：删除信号灯<br />
arg：各个量使用与cmd设置有关<br />
返回：成功返回与cmd相关的正数，错误返回-1</p>
<p><span style="color: #ff0000;">注意：信号量一旦创建就会一直存在系统中，直到手动删除或者重启系统。可以使用ipcs -s命令来查看系统存在的信号量。</span></p>
<p>例子：</p>
<pre class="brush: cpp; title: ; notranslate">
/****************************************
 *
 * 使用信号量进行进程通信——进程1
 * 该进程用于创建信号量
 * 龙昌博客：http://www.xefan.com
 *
 ****************************************/
#include &lt;sys/types.h&gt;
//书上说是用sys/ipc.h和sys/sem.h这两个头文件，但是我用了出错，
//而用linux/ipc.h和linux/sem.h却没问题
//#include &lt;sys/ipc.h&gt;
//#include &lt;sys/sem.h&gt;
#include &lt;linux/sem.h&gt;
#include &lt;linux/ipc.h&gt;
#include &lt;errno.h&gt;
#include &lt;math.h&gt;

int main(int argc, char *argv[])
{
    int key, sid, pid;
    union semun val;
    val.val = 1;
    key = ftok(&quot;tmp&quot;,10);
    if ((sid = semget(key, 1, IPC_CREAT)) &lt; 0)
    {
        perror(&quot;semget&quot;);
        exit(-1);
    }
    printf(&quot;key: %d  sid:%d\n&quot;, key, sid);

    if ((semctl(sid, 0, SETVAL, val)) &lt; 0)
    {
        perror(&quot;semctl&quot;);
        exit(-1);
    }
    if ((semctl(sid, 0, GETVAL, val)) &lt; 0)
    {
        perror(&quot;semctl&quot;);
        exit(-1);
    }
    printf(&quot;sem_val:%d\n&quot;, val.val);

    struct sembuf p_op, v_op;
    p_op.sem_num = 0;
    p_op.sem_op = -1;
    //获取信号
    if (semop(sid, &amp;p_op, 1) &lt; 0) //p op
    {
        perror(&quot;smeop&quot;);
        exit(-1);
    }
    printf(&quot;father get the semaphore\n&quot;);
    sleep(8);
    printf(&quot;father release the senaphore\n&quot;);
    v_op.sem_num = 0;
    v_op.sem_op = 1;
    v_op.sem_flg = 0;
    //释放信号
    if (semop(sid, &amp;v_op, 1) &lt; 0) //v op
    {
        perror(&quot;semop&quot;);
        exit(-1);
    }
    return 0;
}
</pre>
<p>&nbsp;</p>
<pre class="brush: cpp; title: ; notranslate">
/****************************************
 *
 * 使用信号量进行进程通信——进程2
 * 该进程用于获取信号量
 * 龙昌博客：http://www.xefan.com
 *
 ****************************************/
#include &lt;sys/types.h&gt;
//书上说是用sys/ipc.h和sys/sem.h这两个头文件，但是我用了出错，
//而用linux/ipc.h和linux/sem.h却没问题
//#include &lt;sys/ipc.h&gt;
//#include &lt;sys/sem.h&gt;
#include &lt;linux/sem.h&gt;
#include &lt;linux/ipc.h&gt;
#include &lt;errno.h&gt;
#include &lt;math.h&gt;

int main(int argc, char *argv[])
{
    int key, sid, pid;
    key = ftok(&quot;tmp&quot;,10);
    if ((sid = semget(key, 1, IPC_CREAT)) &lt; 0)
    {
        perror(&quot;semget&quot;);
        exit(-1);
    }
    printf(&quot;key: %d  sid:%d\n&quot;, key, sid);

    struct sembuf p_op, v_op;
    p_op.sem_num = 0;
    p_op.sem_op = -1;
    //p_op.sem_flg = 0;
    if (semop(sid, &amp;p_op, 1) &lt; 0) //p op
    {
        perror(&quot;smeop&quot;);
        exit(-1);
    }
    printf(&quot;father get the semaphore\n&quot;);
    sleep(8);
    printf(&quot;father release the senaphore\n&quot;);
    v_op.sem_num = 0;
    v_op.sem_op = 1;
    v_op.sem_flg = 0;
    if (semop(sid, &amp;v_op, 1) &lt; 0) //v op
    {
        perror(&quot;semop&quot;);
        exit(-1);
    }
    return 0;
}
</pre>
<p>先运行进程1，再运行进程2查看效果</p>
]]></content:encoded>
			<wfw:commentRss>http://www.xefan.com/archives/83700.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linux进程通信——使用共享内存</title>
		<link>http://www.xefan.com/archives/83695.html</link>
		<comments>http://www.xefan.com/archives/83695.html#comments</comments>
		<pubDate>Wed, 22 Feb 2012 10:31:00 +0000</pubDate>
		<dc:creator>龍昌</dc:creator>
				<category><![CDATA[编程开发]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.xefan.com/?p=83695</guid>
		<description><![CDATA[头文件： #include &#60;sys/ipc.h&#62; #include &#60;sys/shm.h&#62; 函数：shmget 分配共享内存 函数原型： int shmget(key_t key, size_t size, int shmflg)； key：键值，当为IPC_PRIVATE时新建一块共享内存；若为0时而shmflg中设了IPC_PRIVATE也将新建。 size：内存大小。 shmflg：标志。 IPC_CREAT：内存不存在则新建，否则打开； IPC_EXCL：只有在内存不存在时才创建，否则出错。 返回：成功则返回标识符，出错返回-1 函数： void *shmat(int shmid, char *shmaddr, int shmflg)； shmid：通过shmget获取 shmaddr：映射到进程地址空间的起始地址，设为NULL将自动分配 shmflg：标志；SHM-RDONLY为只读，否则可读可写 返回：成功则返回内存起始地址，失败返回-1 函数： int shmdt(const void *shmaddr)； 使共享内存区脱离映射的进程的地址空间 返回：成功返回0，错误返回-1 &#8230; <a href="http://www.xefan.com/archives/83695.html">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>头文件： #include &lt;sys/ipc.h&gt;<br />
#include &lt;sys/shm.h&gt;</p>
<p>函数：shmget 分配共享内存<br />
函数原型： int shmget(key_t key, size_t size, int shmflg)；<br />
key：键值，当为IPC_PRIVATE时新建一块共享内存；若为0时而shmflg中设了IPC_PRIVATE也将新建。<br />
size：内存大小。<br />
shmflg：标志。<br />
IPC_CREAT：内存不存在则新建，否则打开；<br />
IPC_EXCL：只有在内存不存在时才创建，否则出错。<br />
返回：成功则返回标识符，出错返回-1</p>
<p>函数： void *shmat(int shmid, char *shmaddr, int shmflg)；<br />
shmid：通过shmget获取<br />
shmaddr：映射到进程地址空间的起始地址，设为NULL将自动分配<br />
shmflg：标志；SHM-RDONLY为只读，否则可读可写<br />
返回：成功则返回内存起始地址，失败返回-1</p>
<p>函数： int shmdt(const void *shmaddr)；<br />
使共享内存区脱离映射的进程的地址空间<br />
返回：成功返回0，错误返回-1</p>
<p>函数： void shmctl(int shmid, int cmd, struct shmid_ds *buf)；<br />
shmid：通过shmget获取<br />
cmd：控制命令，如下：<br />
IPC_STAT：获取内存状态<br />
IPC_SET：改变内存状态<br />
IPC_RMID：删除内存<br />
buf：结构体指针，用于存放共享内存状态<br />
返回：成功返回0，错误返回-1</p>
<p><span style="color: #ff0000;">注意：共享内存一旦创建就会一直存在系统中，直到手动删除或者重启系统。</span><br />
例子：</p>
<pre class="brush: cpp; title: ; notranslate">
/**************************************
 *
 * 使用共享内存进行进程通信
 * 龙昌博客：http://www.xefan.com
 *
**************************************/
#include &lt;sys/ipc.h&gt;
#include &lt;sys/shm.h&gt;
#include &lt;sys/stat.h&gt;
#include &lt;errno.h&gt;
#include &lt;string.h&gt;

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        printf(&quot;Usage:%s str\n&quot;, argv[0]);
        exit(1);
    }
    int shmid;
    char *p_addr, *c_addr;
    //创建共享内存
    if ((shmid=shmget(IPC_PRIVATE, 1024, IPC_CREAT)) == -1)
    {
        perror(&quot;shmget&quot;);
        exit(errno);
    }
    if(fork() &gt; 0)	//父进程向内存写入数据
    {
        //获取内存起始地址
	p_addr = shmat(shmid, 0, 0);
        memset(p_addr, 0, 1024);
	//向内存中写入数据
        strncpy(p_addr, argv[1], 1024);
        shmdt(p_addr);
        sleep(3);
        wait(0);
    }
    else		//子进程从内存中读取数据
    {
        //获取内存起始地址
        c_addr = shmat(shmid, 0, 0);
        sleep(4);
        printf(&quot;child get %s\n&quot;, c_addr);
        shmdt(c_addr);
    }
    //删除共享内存
    if (shmctl(shmid, IPC_RMID, NULL) &lt; 0)
    {
        perror(&quot;shmctl&quot;);
        exit(1);
    }
    return 0;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.xefan.com/archives/83695.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linux进程通信——使用信号</title>
		<link>http://www.xefan.com/archives/83692.html</link>
		<comments>http://www.xefan.com/archives/83692.html#comments</comments>
		<pubDate>Wed, 22 Feb 2012 01:54:43 +0000</pubDate>
		<dc:creator>龍昌</dc:creator>
				<category><![CDATA[编程开发]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.xefan.com/?p=83692</guid>
		<description><![CDATA[函数：signal 设置某一信号对应的动作 头文件： #include &#60;signal.h&#62; 函数原型： void (*signal(int signum, void (*handler) (int))) (int)； signal：信号编号 handler：信号处理函数，若该参数不是函数指针则必须为以下两个常数之一： SIG_IGN：忽略信号 SIG_DFL：重设为预设的处理方式 返回：成功则返回先前的信号处理函数指针，错误则返回SIG_ERR(-1) 函数：pause 让进程暂停直到信号出现 头文件：#include &#60;unistd.h&#62; 函数原型： int pause(void)； 只返回-1 函数： kill 传送信号 头文件： #include &#60;signal.h&#62; #include &#60;sys/types.h&#62; 函数原型： int kill(pid_t pid, int sig)； &#8230; <a href="http://www.xefan.com/archives/83692.html">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>函数：signal 设置某一信号对应的动作<br />
头文件： #include &lt;signal.h&gt;<br />
函数原型： void (*signal(int signum, void (*handler) (int))) (int)；<br />
signal：信号编号<br />
handler：信号处理函数，若该参数不是函数指针则必须为以下两个常数之一：<br />
SIG_IGN：忽略信号<br />
SIG_DFL：重设为预设的处理方式<br />
返回：成功则返回先前的信号处理函数指针，错误则返回SIG_ERR(-1)</p>
<p>函数：pause 让进程暂停直到信号出现<br />
头文件：#include &lt;unistd.h&gt;<br />
函数原型： int pause(void)；<br />
只返回-1</p>
<p>函数： kill 传送信号<br />
头文件：<br />
#include &lt;signal.h&gt;<br />
#include &lt;sys/types.h&gt;<br />
函数原型： int kill(pid_t pid, int sig)；<br />
pid：接收信号的进程号；当pid=0时为相同进程组的所有进程；当pid=-1时为系统内所有进程；当pid&gt;0时为指定进程；当pid&lt;-1时为进程组识别码为pid绝对值的所有进程。<br />
sig：要传送的信号<br />
返回：成功返回0，错误返回-1</p>
<p>例子：</p>
<pre class="brush: cpp; title: ; notranslate">
/****************************************
 *
 *设置信号处理
 *等待2秒后向进程本身传送一个SIGALRM信号
 *龙昌博客：http://www.xefan.com
 *
 ****************************************/
#include &lt;signal.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;unistd.h&gt;

void func(int sig_no)
{
    if (sig_no == SIGALRM)
    {
        printf(&quot;get SIGALRM\n&quot;);
    }
}

int main()
{
    printf(&quot;%d waiting for signal..\n&quot;, getpid());
    alarm(2);
    signal(SIGALRM, func);
    raise(SIGALRM);
    pause();
    return 0;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.xefan.com/archives/83692.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linux进程通信——使用有名管道</title>
		<link>http://www.xefan.com/archives/83689.html</link>
		<comments>http://www.xefan.com/archives/83689.html#comments</comments>
		<pubDate>Tue, 21 Feb 2012 10:16:12 +0000</pubDate>
		<dc:creator>龍昌</dc:creator>
				<category><![CDATA[编程开发]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.xefan.com/?p=83689</guid>
		<description><![CDATA[无名管道只能用于父子进程通信，而有名管道可以用于任意进程间通信。 头文件： #include &#60;sys/types.h&#62; #include &#60;sys/stat.h&#62; 函数： int mkfifo(const char *filename, mode_t mode); 创建有名管道对应的实名文件，该文件必须事先不存在。 返回0代表创建成功，否则返回-1。 filename：文件路径 mode：文件权限 创建成功之后可以像操作普通文件一样使用read、write进行读写操作。 例子： 先运行写进程再运行读进程]]></description>
			<content:encoded><![CDATA[<p>无名管道只能用于父子进程通信，而有名管道可以用于任意进程间通信。<br />
头文件：<br />
#include &lt;sys/types.h&gt;<br />
#include &lt;sys/stat.h&gt;</p>
<p>函数：<br />
int mkfifo(const char *filename, mode_t mode);<br />
创建有名管道对应的实名文件，该文件必须事先不存在。<br />
返回0代表创建成功，否则返回-1。<br />
filename：文件路径<br />
mode：文件权限</p>
<p>创建成功之后可以像操作普通文件一样使用read、write进行读写操作。</p>
<p>例子：</p>
<pre class="brush: cpp; title: ; notranslate">
/**************************************
 *
 * 使用有名管道进行进程通信——写进程
 * 文件名：fifo_write.c
 * 龙昌博客：http://www.xefan.com
 *
**************************************/

#include &lt;sys/stat.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;errno.h&gt;

#define FIFO &quot;/tmp/myfifo&quot;

int main(int argc, char *argv[])
{
    int fd;
    char buf[100];
    int num;

    unlink(FIFO);	//先删除文件
    //创建有名管道
    if ( (mkfifo(FIFO, O_CREAT|O_EXCL|O_RDWR) &lt; 0) &amp;&amp; (errno != EEXIST))
    {
        perror(&quot;mkfifo&quot;);
    }

    fd = open(FIFO, O_WRONLY);
    if (fd &lt; 0)
    {
        perror(&quot;open&quot;);
        exit(1);
    }
    while (1)
    {
        scanf(&quot;%s&quot;, buf);
        if ((num=write(fd, buf, 100)) &lt; 0)
        {
            if(errno == EAGAIN)
            {
                printf(&quot;FIFO has not been read yet.\n&quot;);
            }
        }
    }
    close(fd);
    return 0;
}
</pre>
<pre class="brush: cpp; title: ; notranslate">
/**************************************
 *
 * 使用有名管道进行进程通信——读进程
 * 文件名：fifo_read.c
 * 龙昌博客：http://www.xefan.com
 *
**************************************/
#include &lt;sys/stat.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;errno.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;string.h&gt;

#define FIFO &quot;/tmp/myfifo&quot;

int main(int argc, char *argv[])
{
    int fd;
    int num;
    char buf[100];

    //打开管道文件
    //fd = open(FIFO, O_RDONLY|O_NONBLOCK);	//非阻塞方式打开
    fd = open(FIFO, O_RDONLY);
    if (fd &lt; 0)
    {
        perror(&quot;open&quot;);
        exit(1);
    }
    while (1)
    {
        memset(buf, 0, sizeof(buf));
        if ((num=read(fd, buf, 100)) &lt; 0)
        {
            if (errno == EAGAIN)
            {
                printf(&quot;no data yet\n&quot;);
            }
            sleep(1);
            continue;
        }
        printf(&quot;read  %s  from FIFO\n&quot;, buf);
        sleep(1);
    }
    return 0;
}
</pre>
<p>先运行写进程再运行读进程</p>
]]></content:encoded>
			<wfw:commentRss>http://www.xefan.com/archives/83689.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linux进程通信——使用无名管道</title>
		<link>http://www.xefan.com/archives/83686.html</link>
		<comments>http://www.xefan.com/archives/83686.html#comments</comments>
		<pubDate>Tue, 21 Feb 2012 02:03:01 +0000</pubDate>
		<dc:creator>龍昌</dc:creator>
				<category><![CDATA[编程开发]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.xefan.com/?p=83686</guid>
		<description><![CDATA[头文件： #include &#60;unistd.h&#62; 函数： int pipe(int fd[2]); 创建无名管道。 fd[2]：管道两个文件描述符，fd[0]代表读端（管道头），fd[1]代表写端（管道尾）。 创建成功返回0，失败返回-1。 创建成功之后可以像操作普通文件一样使用read、write进行读写操作。 例子：]]></description>
			<content:encoded><![CDATA[<p>头文件：<br />
#include &lt;unistd.h&gt;</p>
<p>函数：<br />
int pipe(int fd[2]);<br />
创建无名管道。<br />
fd[2]：管道两个文件描述符，fd[0]代表读端（管道头），fd[1]代表写端（管道尾）。<br />
创建成功返回0，失败返回-1。</p>
<p>创建成功之后可以像操作普通文件一样使用read、write进行读写操作。<br />
例子：</p>
<pre class="brush: cpp; title: ; notranslate">
/**********************************
 *
 * 使用无名管道进行进程通信
 * 龙昌博客：http://www.xefan.com
 *
***********************************/
#include &lt;unistd.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;

int main(int argc, char *argv[])
{
    int pfd[2];
    pid_t pid;
    char buf[100];
    int num;

    memset(buf, 0, sizeof(buf));

    if (pipe(pfd) &lt; 0)  //创建无名管道
    {
        perror(&quot;pipe&quot;);
        exit(-1);
    }
    //父进程向管道写数据，子进程从管道读数据
    if ((pid=fork()) == 0)
    {
        sleep(1);
        if ((num=read(pfd[0], buf, 100)) &gt; 0)
        {
            printf(&quot;%d numbers read, %s\n&quot;, num, buf);
        }
    }
    else if (pid &gt; 0)
    {
        if (write(pfd[1], &quot;Hello&quot;, 5) &lt; 0)
        {
            perror(&quot;write&quot;);
        }
        if (write(pfd[1], &quot; Pipe&quot;, 5) &lt; 0)
        {
            perror(&quot;write&quot;);
        }
        waitpid(pid, NULL, 0);
    }
    close(pfd[0]);
    close(pfd[1]);
    return 0;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.xefan.com/archives/83686.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linux多进程编程</title>
		<link>http://www.xefan.com/archives/83680.html</link>
		<comments>http://www.xefan.com/archives/83680.html#comments</comments>
		<pubDate>Mon, 20 Feb 2012 10:25:20 +0000</pubDate>
		<dc:creator>龍昌</dc:creator>
				<category><![CDATA[编程开发]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.xefan.com/?p=83680</guid>
		<description><![CDATA[创建进程 所需头文件： #include &#60;unistd.h&#62; #include &#60;sys/types.h&#62; 函数： pid_t fork(); 创建一个子进程，在子进程中返回0，在父进程中返回子进程ID，出错则返回-1。 pid_t vfor(); 创建一个子进程，与fork()相似；区别如下： fork()子进程拷贝父进程数据段、堆栈段，vfork()则是共享； fork()父子进程执行顺序不确定，vfork()是先执行完子进程再执行父进程。 pid_t getpid(); 返回当前进程ID pid_t getppid(); 返回父进程ID 进程等待 头文件： #include &#60;sys/wait.h&#62; 函数： pid_t wait(int *status); 等子进程结束之后才运行。 status：接收子进程返回状态 pid_t waitpid(pid_t pid, int *status, int options); 与waitpid()相似。 pid：指定的进程号，当pid=-1时等待任何子进程，相当于wait()； &#8230; <a href="http://www.xefan.com/archives/83680.html">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>创建进程<br />
所需头文件：<br />
#include &lt;unistd.h&gt;<br />
#include &lt;sys/types.h&gt;</p>
<p>函数：<br />
pid_t fork();<br />
创建一个子进程，在子进程中返回0，在父进程中返回子进程ID，出错则返回-1。<br />
pid_t vfor();<br />
创建一个子进程，与fork()相似；区别如下：<br />
fork()子进程拷贝父进程数据段、堆栈段，vfork()则是共享；<br />
fork()父子进程执行顺序不确定，vfork()是先执行完子进程再执行父进程。</p>
<p>pid_t getpid();<br />
返回当前进程ID<br />
pid_t getppid();<br />
返回父进程ID</p>
<p>进程等待<br />
头文件：<br />
#include &lt;sys/wait.h&gt;</p>
<p>函数：<br />
pid_t wait(int *status);<br />
等子进程结束之后才运行。<br />
status：接收子进程返回状态</p>
<p>pid_t waitpid(pid_t pid, int *status, int options);<br />
与waitpid()相似。<br />
pid：指定的进程号，当pid=-1时等待任何子进程，相当于wait()；<br />
status：用于接收进程返回状态；<br />
option：为WNOHANG时若无任何已结束的子进程则马上返回，不予以等待；为WUNTRACES时若子进程暂停则马上返回，不予以理会结束状态。</p>
<p>例子：</p>
<pre class="brush: cpp; title: ; notranslate">
//使用vfor函数创建子进程
//龙昌博客：http://www.xefan.com
#include &lt;unistd.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;sys/wait.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;errno.h&gt;
#include &lt;math.h&gt;

int main(void)
{
	pid_t child;
        int i = 0;

	/* 创建子进程 */
	if((child=vfork())==-1)
	{
		printf(&quot;Fork Error : %s\n&quot;, strerror(errno));
		exit(1);
	}
	else
	{
		if(child &gt; 0)
		{
                        i++;
			printf(&quot;I am the father: %d ;i=%d\n&quot;, getpid(), i);
			exit(0);
		}
		else
		{
                        i++;
			printf(&quot;I am the child:%d ;i=%d\n&quot;,getpid(), i);
                        sleep(1);
			exit(0);
		}
	}
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.xefan.com/archives/83680.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Windows下静态编译Qt4</title>
		<link>http://www.xefan.com/archives/83668.html</link>
		<comments>http://www.xefan.com/archives/83668.html#comments</comments>
		<pubDate>Thu, 29 Dec 2011 14:55:04 +0000</pubDate>
		<dc:creator>龍昌</dc:creator>
				<category><![CDATA[编程开发]]></category>
		<category><![CDATA[Qt]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://www.xefan.com/?p=83668</guid>
		<description><![CDATA[既然是静态编译，那就要编译出来的程序不信赖于任何dll文件。 首先下载qt-win-opensource-4.7.4-mingw.exe： http://get.qt.nokia.com/qt/source/qt-win-opensource-4.7.4-mingw.exe 和MinGW-gcc440_1.zip： http://get.qt.nokia.com/misc/MinGW-gcc440_1.zip 然后依次解压MinGW-gcc440_1.zip、安装qt-win-opensource-4.7.4-mingw.exe。记得要将gcc的目录和qt的目录添加到环境变量中。 然后打开DOS窗口并切换到Qt的目录（比如我的是D:\Qt\4.7.4），再设置两个变量 set QTDIR=D:\Qt\4.7.4 set QMAKESPEC=win32-g++ 再编辑D:\Qt\4.7.4\mkspecs\win32-g++\qmake.conf文件（最好先备份），改两处： QMAKE_LFLAGS = -enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc 修改为 QMAKE_LFLAGS = -static -enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc 再将 QMAKE_LFLAGS_DLL = -shared 修改为 QMAKE_LFLAGS_DLL = -static 再执行命令： configure -platform win32-g++ -release -opensource -static -fast &#8230; <a href="http://www.xefan.com/archives/83668.html">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>既然是静态编译，那就要编译出来的程序不信赖于任何dll文件。<br />
首先下载qt-win-opensource-4.7.4-mingw.exe： http://get.qt.nokia.com/qt/source/qt-win-opensource-4.7.4-mingw.exe<br />
和MinGW-gcc440_1.zip： http://get.qt.nokia.com/misc/MinGW-gcc440_1.zip</p>
<p>然后依次解压MinGW-gcc440_1.zip、安装qt-win-opensource-4.7.4-mingw.exe。记得要将gcc的目录和qt的目录添加到环境变量中。</p>
<p>然后打开DOS窗口并切换到Qt的目录（比如我的是D:\Qt\4.7.4），再设置两个变量<br />
<em>set QTDIR=D:\Qt\4.7.4</em><br />
<em> set QMAKESPEC=win32-g++</em></p>
<p>再编辑D:\Qt\4.7.4\mkspecs\win32-g++\qmake.conf文件（最好先备份），改两处：<br />
<em>QMAKE_LFLAGS = -enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc</em><br />
修改为<br />
<em>QMAKE_LFLAGS = <span style="color: #ff0000;">-static</span> -enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc</em><br />
再将<br />
<em>QMAKE_LFLAGS_DLL = -shared</em><br />
修改为<br />
<em>QMAKE_LFLAGS_DLL = -static</em></p>
<p>再执行命令：<br />
configure -platform win32-g++ <span style="color: #ff0000;">-release</span> -opensource <span style="color: #ff0000;">-static</span> -fast -qt-sql-sqlite -plugin-sql-sqlite -qt-zlib -qt-gif -qt-libpng -qt-libmng -qt-libtiff -qt-libjpeg -no-webkit -nomake examples -nomake docs -nomake demos</p>
<p>如果有提问是否遵守LGPL协议，选y。配置完成后，最后两句是这样的：<br />
Qt is now configured for building. Just run mingw32-make.<br />
To reconfigure, run mingw32-make confclean and configure.</p>
<p>cd src<br />
mingw32-make -i -k</p>
<p>注意：我们只在在Qt子目录src里运行make。不要在整个qt库的大目录下运行make。只在src目录make，这样只编译核心的Qt库和一些插件，节省时间，而且有核心Qt库就够用了。<br />
如果在D:\Qt\4.7.4\ 整个大目录下运行make，那么make还会去重新编译生成tools目录下的代码，重新做工具程序，像assistant.exe、designer.exe、linguist.exe、qmlviewer.exe等等（生成后全在bin目录）。这些工具使用静态库生成后巨大无比。这些工具程序不管是静态链接还是动态链接生成的，对我们编程压根没影响，都一样用。</p>
<p>好了，接下来就是漫长的等待。2个多小时左右就应该可以编译完成了。<br />
此时再用Qt编译生成的可执行文件不用再信赖Qt的动态库了,但是文件比较大随便一个都是10M以上，而且如果使用的是从qt官网下载的MinGW-gcc编译生成的可执行文件还是会信赖mingwm10.dll动态库。这个只需换一个版本的编译器即可，我用的是这个： http://115.com/file/dn3fkn1g</p>
<p>如果嫌这个过程太麻烦可以直接下载我编译好的静态库来使用：<br />
Qt4.7.4_Win32静态库.part1.rar： http://115.com/file/dn3zwayy<br />
Qt4.7.4_Win32静态库.part2.rar： http://115.com/file/dn3zwa9g<br />
这个是完整版的，解压下来有2G多。如果觉得太大了可以下载精简版：<br />
Qt4.7.4_Win32静态库精简版.rar： http://115.com/file/bhy7bat6<br />
精简版只保留了编译时需要的库文件和qmake等必要的工具，解压下来有500M左右。<br />
注意：只有解压到D盘根目录下才能使用<br />
编译器用的是mingw-7.2.exe： http://115.com/file/dn3fkn1g</p>
]]></content:encoded>
			<wfw:commentRss>http://www.xefan.com/archives/83668.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linux下静态编译win32的GTK程序</title>
		<link>http://www.xefan.com/archives/83665.html</link>
		<comments>http://www.xefan.com/archives/83665.html#comments</comments>
		<pubDate>Sun, 27 Nov 2011 03:36:20 +0000</pubDate>
		<dc:creator>龍昌</dc:creator>
				<category><![CDATA[编程开发]]></category>
		<category><![CDATA[gtk]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://www.xefan.com/?p=83665</guid>
		<description><![CDATA[首先感谢hangyu网友分享的GTK静态库。 原帖地址：http://forum.ubuntu.org.cn/viewtopic.php?f=162&#38;t=354286 下载地址：http://code.google.com/p/static-gtk2-mingw32/ 先说一下在Windows下编译的方法。 解压文件，然后进入解压后的bin目录执行命令： pkg-config.exe &#8211;libs &#8211;cflags “gtk+-2.0&#8243; 如果出现以下错误 Package gtk+-2.0 was not found in the pkg-config search path. Perhaps you should add the directory containing `gtk+-2.0.pc&#8217; to the PKG_CONFIG_PATH environment variable No package &#8216;gtk+-2.0&#8242; found 则先执行命令：set PKG_CONFIG_PATH=你的解压路径\lib\pkgconfig 设置PKG_CONFIG_PATH环境变量 我得到的结果是： &#8230; <a href="http://www.xefan.com/archives/83665.html">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>首先感谢hangyu网友分享的GTK静态库。<br />
原帖地址：http://forum.ubuntu.org.cn/viewtopic.php?f=162&amp;t=354286<br />
下载地址：http://code.google.com/p/static-gtk2-mingw32/</p>
<p>先说一下在Windows下编译的方法。</p>
<p>解压文件，然后进入解压后的bin目录执行命令：<br />
<em>pkg-config.exe &#8211;libs &#8211;cflags “gtk+-2.0&#8243;</em><br />
如果出现以下错误<br />
Package gtk+-2.0 was not found in the pkg-config search path.<br />
Perhaps you should add the directory containing `gtk+-2.0.pc&#8217;<br />
to the PKG_CONFIG_PATH environment variable<br />
No package &#8216;gtk+-2.0&#8242; found<br />
则先执行命令：<em>set PKG_CONFIG_PATH=你的解压路径\lib\pkgconfig</em> 设置PKG_CONFIG_PATH环境变量</p>
<p>我得到的结果是：<br />
-mms-bitfields -IE:/Dev-Cpp/gtk+-2.0/include/gtk-2.0 -IE:/Dev-Cpp/gtk+-2.0/lib/gtk-2.0/include -IE:/Dev-Cpp/gtk+-2.0/include/atk-1.0 -IE:/Dev-Cpp/gtk+-2.0/include/cairo -IE:/Dev-Cpp/gtk+-2.0/include/gdk-pixbuf-2.0 -IE:/Dev-Cpp/gtk+-2.0/include/pango-1.0 -IE:/Dev-Cpp/gtk+-2.0/include/glib-2.0 -IE:/Dev-Cpp/gtk+-2.0/lib/glib-2.0/include -IE:/Dev-Cpp/gtk+-2.0/include/pixman-1 -IE:/Dev-Cpp/gtk+-2.0/include -IE:/Dev-Cpp/gtk+-2.0/include/freetype2 -I/gtk-dev/include/libpng14 -LE:/Dev-Cpp/gtk+-2.0/lib -L/gtk-dev/lib -lgtk-win32-2.0 -lgdk-win32-2.0 -limm32 -lshell32 -luuid -latk-1.0 -lpangocairo-1.0 -lgio-2.0 -lshlwapi -ldnsapi -lgdk_pixbuf-2.0 -ltiff -ljpeg -ljasper -lpangoft2-1.0 -lpangowin32-1.0 -lusp10 -lfontconfig -lexpat -lpango-1.0 -lcairo -lpixman-1 -lfreetype -lmsimg32 -lgdi32 -lpng -lz -lm -lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 -lglib-2.0 -lintl -liconv -lws2_32 -lole32</p>
<p>记得保存这个结果，作为编译时的参数在后面要用到。<br />
然后编译一个程序试试，将以下代码保存为test.c文件。</p>
<pre class="brush: cpp; title: ; notranslate">
#include &lt;gtk/gtk.h&gt;
int main(int argc,char *argv[]){
    GtkWidget *window, *label;
    gtk_init(&amp;argc,&amp;argv);
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window),&quot;Hellow World&quot;);
    g_signal_connect(G_OBJECT(window), &quot;destroy&quot;, G_CALLBACK(gtk_main_quit), NULL);
    label = gtk_label_new(&quot;龙昌博客:http://www.xefan.com&quot;);
    gtk_container_add (GTK_CONTAINER (window), label);
    gtk_widget_show_all(window);
    gtk_main();
    return 0;
}
</pre>
<p>执行命令进行编译：<br />
gcc -o test.exe test.c -mms-bitfields -IE:/Dev-Cpp/gtk+-2.0/include/gtk-2.0 -IE:/Dev-Cpp/gtk+-2.0/lib/gtk-2.0/include -IE:/Dev-Cpp/gtk+-2.0/include/atk-1.0 -IE:/Dev-Cpp/gtk+-2.0/include/cairo -IE:/Dev-Cpp/gtk+-2.0/include/gdk-pixbuf-2.0 -IE:/Dev-Cpp/gtk+-2.0/include/pango-1.0 -IE:/Dev-Cpp/gtk+-2.0/include/glib-2.0 -IE:/Dev-Cpp/gtk+-2.0/lib/glib-2.0/include -IE:/Dev-Cpp/gtk+-2.0/include/pixman-1 -IE:/Dev-Cpp/gtk+-2.0/include -IE:/Dev-Cpp/gtk+-2.0/include/freetype2 -I/gtk-dev/include/libpng14 -LE:/Dev-Cpp/gtk+-2.0/lib -L/gtk-dev/lib -lgtk-win32-2.0 -lgdk-win32-2.0 -limm32 -lshell32 -luuid -latk-1.0 -lpangocairo-1.0 -lgio-2.0 -lshlwapi -ldnsapi -lgdk_pixbuf-2.0 -ltiff -ljpeg -ljasper -lpangoft2-1.0 -lpangowin32-1.0 -lusp10 -lfontconfig -lexpat -lpango-1.0 -lcairo -lpixman-1 -lfreetype -lmsimg32 -lgdi32 -lpng -lz -lm -lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 -lglib-2.0 -lintl -liconv -lws2_32 -lole32<br />
如果不出错的话则生成一个test.exe的可执行文件。<br />
如果没有gcc的话，可以下载安装一个MinGW程序，我之前用MinGW的gcc 4.4.0版本来编译结果出错了，然后换了个4.6版本的才能顺利编译，下载地址：http://nuwen.net/mingw.html</p>
<p>然后再介绍下在Linux下交叉编译的方法。</p>
<p>前一篇文章介绍了在Linux下交叉编译Windows程序的方法。现在只需把上面的参数的路径改下即可。<br />
我的Windows的E盘在Linux下挂载到/mnt/Win_E ，再用上面的程序测试，执行命令：<br />
i486-mingw32-gcc -o test.exe test.c -mms-bitfields -I/mnt/Win_E/Dev-Cpp/gtk+-2.0/include/gtk-2.0 -I/mnt/Win_E/Dev-Cpp/gtk+-2.0/lib/gtk-2.0/include -I/mnt/Win_E/Dev-Cpp/gtk+-2.0/include/atk-1.0 -I/mnt/Win_E/Dev-Cpp/gtk+-2.0/include/cairo -I/mnt/Win_E/Dev-Cpp/gtk+-2.0/include/gdk-pixbuf-2.0 -I/mnt/Win_E/Dev-Cpp/gtk+-2.0/include/pango-1.0 -I/mnt/Win_E/Dev-Cpp/gtk+-2.0/include/glib-2.0 -I/mnt/Win_E/Dev-Cpp/gtk+-2.0/lib/glib-2.0/include -I/mnt/Win_E/Dev-Cpp/gtk+-2.0/include/pixman-1 -I/mnt/Win_E/Dev-Cpp/gtk+-2.0/include -I/mnt/Win_E/Dev-Cpp/gtk+-2.0/include/freetype2 -I/gtk-dev/include/libpng14  -L/mnt/Win_E/Dev-Cpp/gtk+-2.0/lib -L/gtk-dev/lib -lgtk-win32-2.0 -lgdk-win32-2.0 -limm32 -lshell32 -luuid -latk-1.0 -lpangocairo-1.0 -lgio-2.0 -lshlwapi -ldnsapi -lgdk_pixbuf-2.0 -ltiff -ljpeg -ljasper -lpangoft2-1.0 -lpangowin32-1.0 -lusp10 -lfontconfig -lexpat -lpango-1.0 -lcairo -lpixman-1 -lfreetype -lmsimg32 -lgdi32 -lpng -lz -lm -lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 -lglib-2.0 -lintl -liconv -lws2_32 -lole32<br />
然后生成 test.exe文件，可以用wine来测试下是否可用。</p>
<p>这个生成的文件好像有点大了，随便一个都是25M以上。使用命令：<br />
i486-mingw32-strip hellow.exe<br />
一下子可以减到7M左右。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.xefan.com/archives/83665.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

