C 启用linux服务以显示弹出窗口

C 启用linux服务以显示弹出窗口,c,linux,centos6,init,gtk2,C,Linux,Centos6,Init,Gtk2,我使用C语言开发了一个IP messenger,我希望与大家分享它的一些实现细节,以便完全理解我的问题 使用GTK+-2.0库显示GUI窗口 它有一个侦听套接字,每当一个新连接到达时,它就会创建一个新进程来服务于该连接 每当新消息到达时,它将显示一个GUI窗口以显示收到的消息(如弹出窗口) 它需要根权限才能运行,因为它使用原始套接字发送ICMP回显数据包来标识本地网络中的可用主机。(原始套接字需要超级权限) 该进程已被妖魔化,因此它将在后台运行,并仅在消息到达时显示弹出窗口 我的机器是CentO

我使用C语言开发了一个IP messenger,我希望与大家分享它的一些实现细节,以便完全理解我的问题

  • 使用GTK+-2.0库显示GUI窗口
  • 它有一个侦听套接字,每当一个新连接到达时,它就会创建一个新进程来服务于该连接
  • 每当新消息到达时,它将显示一个GUI窗口以显示收到的消息(如弹出窗口)
  • 它需要根权限才能运行,因为它使用原始套接字发送ICMP回显数据包来标识本地网络中的可用主机。(原始套接字需要超级权限)
  • 该进程已被妖魔化,因此它将在后台运行,并仅在消息到达时显示弹出窗口
  • 我的机器是CentOS 6.9
  • 当我从终端开始这个过程时,一切都很完美。但随后我通过在
    /etc/init.d/
    目录中添加启动脚本,为该程序创建了一个启动条目,以将其作为服务运行。 然后我用service命令启动了我的服务

     # service ipmsnger start
    

    现在我可以通过使用
    ps
    命令看到进程正在运行。但是如果消息到达,它不会显示弹出窗口。邮件发件人从messenger获取成功传递报告。原因是什么?用户从终端启动demon进程和系统将其作为启动服务启动有什么区别

    我不太熟悉init.d,因为systemd现在更为常见。 我假设你在运行X11,而不是Wayland

    任用 并以用户身份运行程序,此时将显示对话框

    或者以root用户身份运行程序,在显示时更改为要显示的用户的UID。 您还必须将
    DISPLAY
    设置为
    unix:path=/run/user//BUS


    libnotify的示例

    #include <libnotify/notify.h>
    #include <unistd.h>
    #include <errno.h>
    
    int main(void) {
        if (getuid() != (uid_t)1000 && setuid(1000) == -1) {
            perror("setuid");
            return -1;
        }
        if (setenv("DISPLAY", ":0", 0) == -1) {
              perror("setenv DISPLAY");
              return-1;
        } // guessing 1000 as UID
        if (setenv("DBUS_SESSION_BUS_ADDRESS", "unix:path=/run/user/1000/bus", 1) == -1) {
            perror("setenv DBUS");
            return-1;
        }
    
        notify_init ("Hello world!");
        NotifyNotification * Hello = notify_notification_new("Hello world",
                "This is an example notification.", "dialog-information");
        notify_notification_show(Hello, NULL);
    
        g_object_unref(G_OBJECT(Hello));
        notify_uninit();
    
        return 0;
    }
    
    #包括
    #包括
    #包括
    内部主(空){
    如果(getuid()!=(uid_t)1000&&setuid(1000)=-1){
    佩罗尔(“setuid”);
    返回-1;
    }
    如果(setenv(“显示“,”:0”,0)=-1){
    perror(“setenv显示”);
    返回-1;
    }//猜测1000为UID
    if(setenv(“DBUS会话总线地址”,“unix:path=/run/user/1000/BUS”,1)=-1){
    perror(“setenv DBUS”);
    返回-1;
    }
    通知_init(“你好,世界!”);
    NotifyNotification*Hello=notify\u notification\u new(“Hello world”,
    “这是一个示例通知。”,“对话框信息”);
    notify\u notification\u show(你好,空);
    g_object_unref(g_object(Hello));
    通知_uninit();
    返回0;
    }
    
    我不太熟悉init.d,因为systemd现在更为常见。 我假设你在运行X11,而不是Wayland

    任用 并以用户身份运行程序,此时将显示对话框

    或者以root用户身份运行程序,在显示时更改为要显示的用户的UID。 您还必须将
    DISPLAY
    设置为
    unix:path=/run/user//BUS


    libnotify的示例

    #include <libnotify/notify.h>
    #include <unistd.h>
    #include <errno.h>
    
    int main(void) {
        if (getuid() != (uid_t)1000 && setuid(1000) == -1) {
            perror("setuid");
            return -1;
        }
        if (setenv("DISPLAY", ":0", 0) == -1) {
              perror("setenv DISPLAY");
              return-1;
        } // guessing 1000 as UID
        if (setenv("DBUS_SESSION_BUS_ADDRESS", "unix:path=/run/user/1000/bus", 1) == -1) {
            perror("setenv DBUS");
            return-1;
        }
    
        notify_init ("Hello world!");
        NotifyNotification * Hello = notify_notification_new("Hello world",
                "This is an example notification.", "dialog-information");
        notify_notification_show(Hello, NULL);
    
        g_object_unref(G_OBJECT(Hello));
        notify_uninit();
    
        return 0;
    }
    
    #包括
    #包括
    #包括
    内部主(空){
    如果(getuid()!=(uid_t)1000&&setuid(1000)=-1){
    佩罗尔(“setuid”);
    返回-1;
    }
    如果(setenv(“显示“,”:0”,0)=-1){
    perror(“setenv显示”);
    返回-1;
    }//猜测1000为UID
    if(setenv(“DBUS会话总线地址”,“unix:path=/run/user/1000/BUS”,1)=-1){
    perror(“setenv DBUS”);
    返回-1;
    }
    通知_init(“你好,世界!”);
    NotifyNotification*Hello=notify\u notification\u new(“Hello world”,
    “这是一个示例通知。”,“对话框信息”);
    notify\u notification\u show(你好,空);
    g_object_unref(g_object(Hello));
    通知_uninit();
    返回0;
    }
    
    当您从终端窗口启动程序时,它与您当前的登录会话相关联。这为它提供了在GUI中显示弹出窗口所需的上下文

    但请记住,Linux是一个多用户系统,甚至支持多个并发GUI会话。每个GUI属于一个会话;这台机器没有一个真正的GUI。如果您将程序作为系统服务启动,那么它不会与任何特定的登录会话连接,因此它不知道在那里显示任何GUI

    考虑到该服务以root权限运行,它可能会发现登录会话并在其中弹出消息,但这不是免费的


    我推断,将您的程序作为服务运行的目的是让无法断言根权限的人可以使用它。在这种情况下,我建议重构为两个程序:一个作为根用户运行的服务,一个没有权限运行的客户端。用户希望在希望接收弹出窗口的会话中以自己的身份运行客户端。客户机向服务器注册自身。服务器接收来自网络的消息,并将它们分发给注册的客户端,以便它们显示。

    当您从终端窗口启动程序时,它与您当前的登录会话相关联。这为它提供了在GUI中显示弹出窗口所需的上下文

    但请记住,Linux是一个多用户系统,甚至支持多个并发GUI会话。每个GUI属于一个会话;这台机器没有一个真正的GUI。如果您将程序作为系统服务启动,那么它不会与任何特定的登录会话连接,因此它不知道在那里显示任何GUI

    考虑到该服务以root权限运行,它可能会发现登录会话并在其中弹出消息,但这不是免费的

    我推断,将您的程序作为服务运行的目的是让无法使用服务的人可以使用它