⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 基于 linux 和 minigui 的嵌入式系统软件开发指南(六).htm

📁 详细的介绍了minigui的原理及其在linux上的实现.
💻 HTM
📖 第 1 页 / 共 5 页
字号:
      <P>前一类用来将某个 16位、32 位或者 64 位整数从某个特定的字节序转换为系统私有(native)字节序。举例如下: 
      <TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc 
        border=1><TBODY>
        <TR>
          <TD><PRE><CODE>
    int fd, len_header;

...

    if (read (fd, &amp;len_header, sizeof (int)) == -1)
        goto error;
#if MGUI_BYTEORDER == MGUI_BIG_ENDIAN
    len_header = ArchSwap32 (len_header);	// 如果是 Big Endian 系统,则转换字节序
#endif
...
</CODE></PRE></TD></TR></TBODY></TABLE></P>
      <P>在上面的程序段中,首先通过 read 系统调用从指定的文件描述符中读取一个整数值到 len_header 变量中。该文件中保存的整数值是 
      Little Endian 的,因此如果在 Big Endian 系统上使用这个整数值,就必须进行字节顺序交换。这里可以使用 
      ArchSwapLE32,将 Little Endian 的 32 位整数值转换为系统私有的字节序。也可以如上述程序段那样,只对 Big 
      Endian 系统进行字节序转换,这时,只要利用 ArchSwap32 函数即可。</P>
      <P>MiniGUI 提供的用来转换字节序的函数(或者宏)如下: 
      <UL class=n01>
        <LI>ArchSwapLE16(X) 将指定的以 Little Endian 字节序存放的 16 位整数值转换为系统私有整数值。如果系统本身是 
        Little Endian 系统,则该函数不作任何工作,直接返回 X;如果系统本身是 Big Endian 系统,则调用 ArchSwap16 
        函数交换字节序。 
        <LI>ArchSwapLE32(X) 将指定的以 Little Endian 字节序存放的 32 位整数值转换为系统私有整数值。如果系统本身是 
        Little Endian 系统,则该函数不作任何工作,直接返回 X;如果系统本身是 Big Endian 系统,则调用 ArchSwap32 
        函数交换字节序。 
        <LI>ArchSwapBE16(X) 将指定的以 Big Endian 字节序存放的 16 位整数值转换为系统私有整数值。如果系统本身是 
        Big Endian 系统,则该函数不作任何工作,直接返回 X;如果系统本身是 Little Endian 系统,则调用 ArchSwap16 
        函数交换字节序。 
        <LI>ArchSwapBE32(X) 将指定的以 Big Endian 字节序存放的 32 位整数值转换为系统私有整数值。如果系统本身是 
        Big Endian 系统,则该函数不作任何工作,直接返回 X;如果系统本身是 Little Endian 系统,则调用 ArchSwap32 
        函数交换字节序。 </LI></UL>
      <P></P>
      <P>MiniGUI 提供的第二类函数用来从标准 I/O 的文件对象中读写 Endian 整数值。如果要读取的文件是以 Little Endian 
      字节序存放的,则可以使用 MGUI_ReadLE16 和MGUI_ReadLE32 
      等函数读取整数值,这些函数将把读入的整数值转换为系统私有字节序,反之使用MGUI_ReadBE16 和MGUI_ReadBE32 
      函数。如果要写入的文件是以 Little Endian 字节序存放的,则可以使用 MGUI_WriteLE16 和MGUI_WriteLE32 
      等函数读取整数值,这些函数将把要写入的整数值从系统私有字节序转换为 Little Endian 
      字节序,然后写入文件,反之使用MGUI_WriteBE16 和MGUI_WriteBE32 函数。下面的代码段说明了上述函数的用法: 
      <TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc 
        border=1><TBODY>
        <TR>
          <TD><PRE><CODE>
    FILE* out;
    int ount;
...
    MGUI_WriteLE32 (out, count);  // 以 Little Endian 字节序保存 count 到文件中。
...
</CODE></PRE></TD></TR></TBODY></TABLE></P>
      <P><SPAN class=atitle3>4.2 
      利用条件编译编写可移植代码</SPAN><BR>在涉及到可移植性问题的时候,有时我们能够方便地通过 4.1 
      中描述的方法进行函数封装,从而提供具有良好移植性的代码,但有时我们无法通过函数封装的方法提供可移植性代码。这时,恐怕只能使用条件编译了。下面的代码说明了如何使用条件编译的方法确保程序正常工作(该代码来自 
      MiniGUI src/kernel/sharedres.c): 
      <TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc 
        border=1><TBODY>
        <TR>
          <TD><PRE><CODE>
/* 如果系统不支持共享内存,则定义 _USE_MMAP
#undef  _USE_MMAP 
/* #define _USE_MMAP 1 */

void *LoadSharedResource (void)
{
#ifndef _USE_MMAP
    key_t shm_key;
    void *memptr;
    int shmid;
#endif

    /* 装载共享资源 */
    ...

#ifndef _USE_MMAP /* 获取共享内存对象 */
    if ((shm_key = get_shm_key ()) == -1) {
        goto error;
    }
    shmid = shmget (shm_key, mgSizeRes, SHM_PARAM | IPC_CREAT | IPC_EXCL); 
    if (shmid == -1) { 
        goto error;
    } 

    // Attach to the share memory. 
    memptr = shmat (shmid, 0, 0);
    if (memptr == (char*)-1) 
        goto error;
    else {
        memcpy (memptr, mgSharedRes, mgSizeRes);
        free (mgSharedRes);
    }

    if (shmctl (shmid, IPC_RMID, NULL) &lt; 0) 
        goto error;
#endif

    /* 打开文件 */
    if ((lockfd = open (LOCKFILE, O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1)
        goto error;

#ifdef _USE_MMAP
    /* 如果使用 mmap,就将共享资源写入文件 */
    if (write (lockfd, mgSharedRes, mgSizeRes) &lt; mgSizeRes)
        goto error;
    else
    {
        free(mgSharedRes);
        mgSharedRes = mmap( 0, mgSizeRes, PROT_READ|PROT_WRITE, MAP_SHARED, lockfd, 0);
    }
#else
    /* 否则将共享内存对象 ID 写入文件 */
    if (write (lockfd, &amp;shmid, sizeof (shmid)) &lt; sizeof (shmid))
        goto error;
#endif

    close (lockfd);

#ifndef _USE_MMAP
    mgSharedRes = memptr;
    SHAREDRES_SHMID = shmid;
#endif
    SHAREDRES_SEMID = semid;

    return mgSharedRes; 

error:
    perror ("LoadSharedResource"); 
    return NULL;
}</CODE></PRE></TD></TR></TBODY></TABLE></P>
      <P>上述程序段是 MiniGUI-Lite 
      服务器程序用来装载共享资源的。如果系统支持共享内存,则初始化共享内存对象,并将装载的共享资源关联到共享内存对象,然后将共享内存对象 ID 
      写入文件;如果系统不支持共享内存,则将初始化后的共享资源全部写入文件。在客户端,如果支持共享内存,则可以从文件中获得共享内存对象 
      ID,并直接关联到共享内存;如果不支持共享内存,则可以使用 mmap 系统调用,将文件映射到进程的地址空间。客户端的代码段如下: 
      <TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc 
        border=1><TBODY>
        <TR>
          <TD><PRE><CODE>
void* AttachSharedResource (void)
{
#ifndef _USE_MMAP
    int shmid;
#endif
    int lockfd;
    void* memptr;

    if ((lockfd = open (LOCKFILE, O_RDONLY)) == -1)
        goto error;

#ifdef _USE_MMAP
    /* 使用 mmap 将共享资源映射到进程地址空间 */
    mgSizeRes = lseek (lockfd, 0, SEEK_END );
    memptr = mmap( 0, mgSizeRes, PROT_READ, MAP_SHARED, lockfd, 0);
#else
    /* 否则获取共享内存对象 ID,并关联该共享内存 */
    if (read (lockfd, &amp;shmid, sizeof (shmid)) &lt; sizeof (shmid))
        goto error;
    close (lockfd);

    memptr = shmat (shmid, 0, SHM_RDONLY);
#endif
    if (memptr == (char*)-1) 
        goto error;
    return memptr;

error:
    perror ("AttachSharedResource"); 
    return NULL;
}</CODE></PRE></TD></TR></TBODY></TABLE></P>
      <P><A name=5><SPAN class=atitle2>5 其他</SPAN></A></P>
      <P><SPAN class=atitle3>5.1 读写配置文件</SPAN><BR>MiniGUI 的配置文件,即 
      /etc/MiniGUI.cfg 文件的格式,采用了类似 Windows INI 文件的格式。这种文件格式非常简单,如下所示: 
      <TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc 
        border=1><TBODY>
        <TR>
          <TD><PRE><CODE>
[section-name1]
key-name1=key-value1
key-name2=key-value2

[section-name2]
key-name3=key-value3
key-name4=key-value4
</CODE></PRE></TD></TR></TBODY></TABLE></P>
      <P>这种配置文件中的参数以 section 分组,然后用 key=value 
      的形式指定参数及其值。应用程序也可以利用这种配置文件格式保存一些配置信息,为此,MiniGUI 
      提供了如下三个函数(include/minigui.h): 
      <TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc 
        border=1><TBODY>
        <TR>
          <TD><PRE><CODE>
int GUIAPI GetValueFromEtcFile (const char* pEtcFile, const char* pSection,const char* pKey, char* pValue, int iLen);
int GUIAPI GetIntValueFromEtcFile (const char* pEtcFile, const char* pSection,const char* pKey, int* value);
int GUIAPI SetValueToEtcFile (const char* pEtcFile, const char* pSection, const char* pKey, char* pValue);
</CODE></PRE></TD></TR></TBODY></TABLE></P>
      <P>这三个函数的用途如下: 
      <UL class=n01>
        <LI>GetValueFromEtcFile:从指定的配置文件当中获取指定的键值,键值以字符串形式返回。 
        <LI>GetIntValueFromEtcFile:从指定的配置文件当中获取指定的整数型键值。该函数将获得的字符串转换为整数值返回(采用strtol 
        函数转换)。 
        <LI>SetValueToEtcFile:该函数将给定的键值保存到指定的配置文件当中,如果配置文件不存在,则将新建配置文件。如果给定的键已存在,则将覆盖旧值。</LI></UL>
      <P></P>
      <P>假定某个配置文件记录了一些应用程序信息,并具有如下格式: 
      <TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc 
        border=1><TBODY>
        <TR>
          <TD><PRE><CODE>
[mginit]
nr=8
autostart=0

[app0]
path=../tools/
name=vcongui
layer=
tip=Virtual&amp;console&amp;on&amp;MiniGUI
icon=res/konsole.gif

[app1]
path=../bomb/
name=bomb
layer=

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -