c - 如何在GTK应用程序(或GTK和控制台应用程序)之间共享内存?

原文 标签 c memory gtk share

我正在尝试交流两个程序(一个使用GTK,另一个使用C编程的标准IO)。在这两者中,我都使用了shmget。 shmat等。

但是,要完成这些工作我很麻烦...两个程序都可以编译,但是它们都没有按照我的意图运行。

我真正想做的是将数据从服务器发送到控制客户端程序的客户端(在此测试中,仅在终端上打印数字),在接收到服务器的信号后,该操作将完成。

不幸的是,我无法使用GTK做到这一点,但是我几乎在控制台应用程序中做到了,但是当它自动运行时(没有用户交互),客户端在65516次迭代后崩溃了。在游戏程序中,这可能是一个问题,但是对于某些应用程序,以下代码可以令人满意地工作。

我的问题是:为什么在达到65516次交互(在客户端程序上调用shmat函数)后发生错误?

在我未来的应用程序中,必须避免此错误,否则它将使程序崩溃。

如何避免这种情况并使我的程序(客户端应用程序)无限期运行?

还有其他方法可以通过另一个程序控制一个程序吗?哪一个可行或更实用?

文件
smh-02.h

#define  NOT_READY  -1
#define  FILLED     0
#define  TAKEN      1

struct Memory 
{
    int  status;
    int  data[4];
    int dado;     // I just add this data
};


文件Console_server01.c

#include  <stdio.h>
#include  <stdlib.h>
#include  <sys/types.h>
#include  <sys/ipc.h>
#include  <sys/shm.h>

#include "shm-02.h"

#define RUN_WITH_USER   // Coment this line to user interactivity
                    // Or uncoment it to run automactic test indefinitely until segmented fail

 key_t          ShmKEY;
 int            ShmID;
 struct Memory  *ShmPTR;

//---------------------------------------------------------------------
void send_data(int info)
{
while(ShmPTR->status != TAKEN);

 ShmPTR->status  = NOT_READY;
 ShmPTR->dado = info;
 ShmPTR->status = FILLED;   //Server has informed client that the shared memory have been FILLED    
}
//---------------------------------------------------------------------
//---------------------------------------------------------------------
int main(int argc, char *argv[]) 
{

int info;

 ShmKEY = ftok(".", 'x');
 ShmID = shmget(ShmKEY, sizeof(struct Memory), IPC_CREAT | 0666);

 if (ShmID < 0) 
    { 
    printf("*** shmget error (server) ***\n");
    exit(1);    
    }

 ShmPTR = (struct Memory *) shmat(ShmID, NULL, 0);

 if ((int) ShmPTR == -1) 
    { 
    printf("*** shmat error (server) ***\n");
    exit(1);     
    }

send_data(55); // This will send some signal to the client establish connection

    info = 1;           //----- Value to RUN_REPEATLY ------

    do
    {
#ifdef RUN_WITH_USER    //----------------------------------
    printf("\n Type:");
    printf("\n [1] To move to RIGHT");
    printf("\n [2] To move to LEFT");
    printf("\n [3] To move to QUIT");
    printf("\n You choice is: ");
    scanf("%d",&info);
#endif              //----------------------------------
    send_data(info);
    }
    while(info != 3);

     shmdt((void *) ShmPTR);         //Server has detached its shared memory...
     shmctl(ShmID, IPC_RMID, NULL); //Server has removed its shared memory...

return 0;
}


文件Console_client01.c

#include  <stdio.h>
#include  <stdlib.h>
#include <unistd.h>
#include  <sys/types.h>
#include  <sys/ipc.h>
#include  <sys/shm.h>

#include "shm-02.h"

int  main(void)
{
key_t          ShmKEY;
 int            ShmID;
 struct Memory  *ShmPTR;
ShmKEY = ftok(".", 'x');

int i = 0;  
int trigger = 0;    // trigger locked
ShmID = shmget(ShmKEY, sizeof(struct Memory), 0666);

    if (ShmID < 0)
        {
          printf("*** shmget error (client) ***\n");
        exit (1); //Client exits
        }

    do{
        ShmPTR = (struct Memory *) shmat(ShmID, NULL, 0);

        if ( (ShmPTR->status == FILLED)&&(trigger == 0) )
            {
            ShmPTR->status = TAKEN;
            trigger = 1;    // trigger pulled
            }

            while (ShmPTR->status != FILLED)
                {
                printf("\nWaiting status = FILLED\t|\t");
                switch(ShmPTR->status)
                {
                case -1:
                    printf("Current status = NOT_READY");
                    break;
                case 0:
                    printf("Current status = FILLED");
                    break;
                case 1:
                    printf("Current status = TAKEN");
                    break;
                }
                sleep(1); // Uncoment this line to better user interactivity
                }

        usleep(800);    // Uncoment this line to better user interactivity
        i++;
        printf("\ni = %d --/// | dado = %d ", i, ShmPTR->dado);

        if ((int) ShmPTR == -1) 
            {
            printf("*** shmat error (client) ***\n");
            exit(1);    //Client exits 
            }
        else
            {
            if (ShmPTR->dado == 55)
                {   
                printf("\nConnection ESTABLISHED"); //Go to the LEFT
                ShmPTR->status = TAKEN;
                }

            if (ShmPTR->dado == 3)  // Exiting Program
                {
                ShmPTR->status = TAKEN;     //Client has informed server data have been taken...
                shmdt((void *) ShmPTR); //Client has detached its shared memory...
                exit (0); //Client exits 
                }

            if (ShmPTR->dado == 1)
                {   
                printf("\n<--- move LEFT"); //Go to the LEFT
                ShmPTR->status = TAKEN;
                }

            if (ShmPTR->dado == 2)  
                {
                printf("\n---> move RIGHT");    // Go to the RIGHT
                ShmPTR->status = TAKEN;
                }

            if ( (ShmPTR->dado != 1)||(ShmPTR->dado != 2) )
                {
                printf("\nIdle | dado = %d",ShmPTR->dado ); //Doing NOTHING
                ShmPTR->status = TAKEN;
                }
            }

    }while (1); // 'Infinite' loop
 exit(0);
}


Running the programs_Picture

Error after 65516 interations_Picture

最佳答案

绝对不要使用共享内存进行通信。它的类型不安全且难以正确编码。

您真正需要的是序列化。考虑使用JSON-RPC进行通信。是的,它远比原始内存操作慢,但更安全,更可移植且更容易工作。 Some even use it for heavy and often loads, let alone occasional loads like GUI input.

关于c - 如何在GTK应用程序(或GTK和控制台应用程序)之间共享内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39708616/

相关文章:

performance - vim 是否将整个文件读入内存

memory - 获取内存中redis的key-value大小

c - 未定义的引用,WebKitGTK

python - Gtk-ERROR **:检测到GTK + 2.x符号。不支持在同一过程中使用GTK + 2.x和GTK + 3(Kivy应用程序)

c - 错误无法将参数'1'的'int **'转换为'int *'到'int show(int *)'

c - 从10x10阵列开始,如何选择10个随机站点

c - Valgrind指示内存泄漏

C - 共享内存 - 共享结构内的动态数组

c - 在k&r book练习1.18中,编写一个程序来删除输入的每一行中的尾随空白和制表符,并删除整个空白行

python - 告诉时PyGTK窗口未隐藏