日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux下程序如何实现单实例运行

發布時間:2023/12/15 linux 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux下程序如何实现单实例运行 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1、技術原理

無論是windows還是linux下,程序設計者都會遇到一個問題,那就是如何實現程序的單實例運行。比如,Windows自帶的播放軟件Windows Medea Player只能啟動一個實例。原因很簡單,如果同時啟動幾個實例,卻播放不同的文件,那么聲音和圖像就會引起混亂。所以,我們要做的就是,程序啟動時檢測一下系統中是否已經存在一個完全一樣的實例,如果已經存在,則本次啟動的程序自動退出。那么,從編碼的角度來分析,該如何實現這個效果呢?在linux系統中,我們一般有以下幾種方法:

  • shell使用ps命令來判斷。最常見也是最簡單的方案,直接寫一個特定的shell腳本來實現。不過存在可移植性差的問題,進程名字一旦改變之后,腳本就失去作用無法監控。同時,還要額外附加這個腳本文件在系統中運行,實在有點多余;
  • 信號量/共享內存。使用共享內存,通過shmget操作共享內存,然后寫入pid,這樣就不用生成可見的文件。這個方案只存在一個很小的缺陷,需要配置共享內存的key,并保證不與系統其他應用沖突,一般來說,沖突概率非常小;
  • 端口搶占。應用于大多數的Linux網絡應用。思路是系統保證每個端口的TCP只能有一個進程監聽,那么如果程序啟動時,監聽一個核心的端口,第二個運行的實例就會監聽失敗,無法啟動。這個方案同樣很有效,省去了一個額外的配置文件,不足之處是一般只用于帶網絡的程序;
  • 創建文件,加鎖(建議性鎖)。這種做法最常見了,應用于大多數的Linux程序,如apache httpd, mysql。思路是配置一個pid文件,當程序啟動時,對pid文件加鎖,然后寫入本進程的pid,如果鎖失敗,說明有實例已經啟動了。這個方案非常可靠,唯一的不足是需要配置一個pid文件,并且保證文件目錄和文件可寫;
  • 進程列表檢測。對于運維常用的方法。由于運維不一定能控制程序的修改,所以考慮從外部解決。crontab腳本,查詢運行的進程數,一旦發現進程數與預期不符,那么killall,重啟進程。這個方案是旁路方案,比上面的方式更通用,還可以監視進程數,避免某些子進程core。這個方案沒有什么缺陷,如果硬要找一個的話,不同的系統ps命令輸出可能不一樣,腳本需要考慮移植。
  • 2、源碼實現

    經過一番對比,優選其中的方案4,也是最大眾化的一個方案。下面就是詳細的代碼實現:

    • single_instance.c源代碼
    /************************************************************************************************** ** ** ** 文件名稱: single_instance.c ** ** 版權所有: CopyRight @ LEON WorkStudio CO.LTD. 2017 ** ** 文件描述: 判斷系統中是否已經存在該進程的實例 ** ** =========================================================================================== ** ** 創建信息: | 2017-9-14 | LEON | 創建本模塊 ** ** =========================================================================================== ** ** 修改信息: 單擊此處添加.... ** **************************************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <printf.h> #include <string.h> #include <errno.h> #include <sys/stat.h>/************************************************************************************************** ** 函數名稱: lockfile ** 功能描述: 對文件加鎖 ** 輸入參數: 無 ** 輸出參數: 無 ** 返回參數: 無 **************************************************************************************************/ static int lockfile(int fd) {struct flock fl;fl.l_type = F_WRLCK;fl.l_start = 0;fl.l_whence = SEEK_SET;fl.l_len = 0;return(fcntl(fd, F_SETLK, &fl)); }/************************************************************************************************** ** 函數名稱: proc_is_exist ** 功能描述: 判斷系統中是否存在該進程 ** 輸入參數: procname: 進程名 ** 輸出參數: 無 ** 返回參數: 返回1表示系統中已經存在該進程了;返回0表示系統中不存在該進程 ** 注意事項: 此處加鎖完后無需對文件進行close,而是進程退出后由系統來釋放;否則無法起到保護的作用 **************************************************************************************************/ int proc_is_exist(const char *procname) {int fd;char buf[16];char filename[100];sprintf(filename, "/var/run/%s.pid", procname);fd = open(filename, O_RDWR | O_CREAT, (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));if (fd < 0) {printf("open file \"%s\" failed!!!\n", filename);return 1;}if (lockfile(fd) == -1) { /* 嘗試對文件進行加鎖 */printf("file \"%s\" locked. proc already exit!!!\n", filename);close(fd);return 1;} else {ftruncate(fd, 0); /* 寫入運行實例的pid */sprintf(buf, "%ld", (long)getpid());write(fd, buf, strlen(buf) + 1);return 0;} }
    • single_instance.h源代碼
    /************************************************************************************************** ** ** ** 文件名稱: single_instance.h ** ** 版權所有: CopyRight @ LEON WorkStudio CO.LTD. 2017 ** ** 文件描述: 判斷系統中是否已經存在該進程的實例 ** ** =========================================================================================== ** ** 創建信息: | 2017-9-14 | LEON | 創建本模塊 ** ** =========================================================================================== ** ** 修改信息: 單擊此處添加.... ** **************************************************************************************************/ #ifndef SINGLE_INSTANCE_H #define SINGLE_INSTANCE_H#ifdef __cplusplus extern "C" { #endifint proc_is_exist(const char *procname);#ifdef __cplusplus } #endif#endif

    3、使用說明

    調用者只需在程序啟動時調用本函數,根據返回值進行判斷即可:

    if (proc_is_exist(g_fk_process_name) == TRUE) { /* 單實例運行 */print_sys("an \"%s\" already running in system. exit now...\n", g_fk_process_name);return 0; } else {print_sys("\"%s\" starting...\n", g_fk_process_name); }

    總結

    以上是生活随笔為你收集整理的linux下程序如何实现单实例运行的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。