精选文章

Android下使用TCPDUMP抓包Wireshark分析数据 如果想分析Android下某个APP的网络数据交互,需要在Android手机上抓包,最常用的抓包工具非tcpdump莫属,用tcpdump生成Wireshark识别的pcap文件,然后将pcap文件下载到电脑上,用电脑上的Wireshark加载pcap文件,通过Wireshark分析tcpdump抓取的数据。...

继续阅读

Mac下部署Android开发环境附加NDK 作为开发者,我们深有体会,不管是进行什么开发,为了部署开发环境,我们往往需要折腾很长时间、查阅很多资料才能完成,而且这次折腾完了,下次到了另一台新电脑上又得重新来过,整个部署过程记得还好,要是不记得又得重新开始,而且遇到Android这种GFW阻隔了开发资源下载链接的环境部署,又尤其浪费时间。所以这也是我写下这篇教程的初衷跟动力源泉,希望大家参考了这篇教程以后可以轻轻松松在Mac系统下将Android环境部署好。...

继续阅读

稍顯嚴肅的台中 坦白說,留在腦海中的台中影像並不多,來台灣之前在Booking上只訂到了台中的一家青旅,第一次住青旅有些不習慣,幹什麼都放不開。 同屋的一個男生是台灣人,不過一年中四分之三的時間在上海跟北京,這麼說來跟我還是比較有共同話題的。得之我準備花15天的時間環島,覺得太倉促了,他們大學時期花一個半月的時間也不見得能將台灣島給逛完。我只能無奈地表示,兩岸允許的簽證時間有限,自己的空閒時間更有限,只能用打卡式的旅行了,我深知正真地旅行應該慢下來,融入當地的環境,感受他們的風土人情,但第一次只能這樣作罷,以後換成民進黨上台,形勢會變成怎樣還不得而知,能否再過來還是個未知數。而我一向信奉的人生格言是秉燭夜遊,活在當下,所以,理解自己吧。...

继续阅读

為之留戀的新竹 來新竹之前本沒有對她有過高的期待,慢慢對她加分要從桃園火車站出發前往新竹開始。 在桃園火車站的候車月台上,有醒目的旅遊資料發放處,這上面的擺放的全是新竹的旅遊宣傳資料,關鍵的是資料做得非常簡潔易懂,而接下來一天的新竹之行就全部是依據這份寶典的指引來完成的。...

继续阅读

從桃園開始台灣之行 初到台灣恰逢華夏銀行系統升級,特意準備的華夏銀聯卡在桃園機場沒能派上用場,只好用建行在機場5000塊,算下來是很不划算的,但是沒辦法,誰叫我出機場就得花錢呢。 從機場打車到桃園的酒店,花了將近六百塊新台幣,到酒店時五點多,天已經漸亮了,洗漱完等到七點吃過早餐就開始補覺囉,一覺醒來已是中午,帶著換下來的衣服外出找自助洗衣店,順便覓食。...

继续阅读

  • Prev
  • Next

多平台防止程序二次启动

文章分类 : C语言, Linux, Windows, 应用与编程, 网络

我们在编写应用程序的过程中,通常会遇到这样的情况,因为某些原因,程序被系统多次或者反复调用,导致程序耗尽系统内存或者出现不可预知的错误,最终影响到程序原本的设计需求,这显然不是我们所希望看到的结果,但是如果在程序内部加上必要的判断,不管系统是否多次调用,都能防止同一时刻多个同样的程序同时运行。    

网络上防止程序二次启动的方法大同小异,最常见的便是程序启动时先检测指定文件是否存在,如果不存在则创建一个文件,退出时删除该文件,否则认为该程序已启动,直接退出。但是这样做有一个潜在的问题,万一程序在退出前崩溃了,指定文件还未来得及删除,则程序将无法再次启动。另外一个问题是,有些特定文件系统是只读属性的,压根就无法创建文件,所以这一方案也不可行。

上面那种办法虽然存在一定限制以及潜在的缺陷,但至少是支持大多数平台的,对于跨平台的程序而言比较有优势。如果程序只运行在特定平台,我们也可以使用各平台特有的办法实现。

Linux平台下,我们可以调用popen函数执行ps命令,结合awk、grep跟wc命令统计当前进程中与当前程序名字相同的进程数量,即执行“ps x | awk ‘{print $5}’ | grep “当前程序名” | wc -l”,看得到的结果是否大于1,倘若大于1则说明在当前程序启动以前已经启动过同样的程序了,当前程序作退出处理。这种方法的存在的隐患也很大,必须确保没有同名或名字相似的其他程序存在,也不允许该程序有多种命名方式,否则判断结果将出现误差。

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

int main(int argc, char *argv[])
{
    int i = 0;
    FILE *stream;
    char recvBuf[256] = {0};
    char cmdBuf[256] = {0};

    sprintf(cmdBuf, "ps x | awk '{print $5}' | grep %s | wc -l", argv[0]);
    stream = popen(cmdBuf, "r");
    fread(recvBuf, sizeof(char), sizeof(recvBuf)-1, stream);
    pclose(stream);

    if (atoi(recvBuf) > 1)
    {
        printf("The number of programs: %s\n", recvBuf);
        printf("The program %s already exist, so exit!\n", argv[0]);
        exit(1);
    }

    //sleep for test
    while(1) sleep(10);

    return 0;
}
 

 
Windows平台下,大多程序都用CreateMutex方式来限制多开。使用API函数CreateMutex来创建命名互斥对象来实现程序互斥是一个比较通用的方法。对于界面程序,我们可以在IninInstance()函数加入互斥对象,对于后台或者控制台程序,我们可以在main()开始的部分加入互斥对象。

#include <Windows.h>

int main(int argc, char* argv[])
{
    HANDLE hMutex = ::CreateMutex(NULL, FALSE, “MYCOMPANY MYAPP.EXE”);
    if( (GetLastError() == ERROR_ALREADY_EXISTS) ||
    (GetLastError() == ERROR_ACCESS_DENIED) )
    {
        CloseHanle( hMutex );
        printf(“程序已经运行!系统不允许重复运行!\n”);
        return FALSE;
    }

    // main code here

    return 0;
}
 

 

Android平台下,因为其采用Linux内核,跟Linux一样的方法便能实现。

以上是网上广为传播的两类最普遍的解决程序多重启动的方法,都在不同程度上存在一定的局限跟隐患。本人想到了一种几乎兼容所有平台且方便使用的方法,那就是在程序启动以后,开始真正的任务之前,先尝试绑定一个系统端口,如果绑定成功,则继续执行其他主要任务,否则端口被其他程序绑定,说明已经有一个同样的程序正在执行,当前程序作退出处理。这样做的坏处是浪费了一个端口,不过这对于大多数业务来说是值得的。需要注意的是,端口默认无法复用,不能人为地设置端口复用,而且该端口应该尽可能取得生僻,以确保不会恰巧被其他程序所占用。

以Linux平台下C语言实现为例,其他平台代码大同小异:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>

int main(void)
{
    int fd;
    struct sockaddr_in addr;

    fd = socket(PF_INET, SOCK_STREAM, 0);
    if (fd < 0)
    {
        perror("socket");
        return -1;
    }

    memset(&addr, 0, sizeof(addr));
    addr.sin_family = PF_INET;
    addr.sin_port = htons(1987);
    addr.sin_addr.s_addr = INADDR_ANY;

    if (bind(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) < 0)
    {
        perror("bind");
        printf("The program already exist, so exit!\n");
        close(fd);
        exit(1);
    }
    else
    {
        while (1) sleep(10);
    }

    return 0;
} 

除非注明,文章均为CppLive 编程在线原创,转载请注明出处,谢谢。

本文地址:https://www.cpplive.com/html/1626.html

这里因为你的留言而存在!!!

You must be logged in to post a comment.