プログラムインスタンスが実行されたか否かを判断するN種類の方法

6077 ワード

1.作成したファイルにプロセスIDを書き込み、機械が正常に終了していない場合は、再起動後にこのファイルを読み取り、プロセスIDを取得し、IDに基づいてプロセスが実行中かどうかを判定し、そうでない場合はファイルを削除する.これにより、ファイルを削除せず、プログラムが実行できないという問題は発生しません.
 
2.ファイルを開き、ロックします.新しく実行したプログラムは、ファイルを再度ロックしようとしますが、ロックされているため、エラーメッセージが返されます.これにより,プログラムが実行されたか否かを判断できる.FD_の設定CLOEXEC後、プログラムが終了する限り、再度ロックできます.通常、スプライトプロセスではapacheなどの方法が使用され、デフォルトでは/var/runディレクトリにあります.
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include 

#define PIDFILE "/var/run/my.pid"
#define write_lock(fd,offset,whence,len) lock_reg(fd,F_SETLK,F_WRLCK,offset,whence,len)
#define FILE_MODE (S_IRWXU|S_IRWXG|S_IRWXO)

int lock_reg (int fd, int cmd, int type, off_t offset, int whence, off_t len)
{
    struct flock lock;

    lock.l_type = type;
    lock.l_start = offset;
    lock.l_whence = whence;
    lock.l_len = len;

    int ret = fcntl(fd, cmd, &lock);
    return ret;
}

bool isSingleton()
{
    int fd,val;
    char buf[10];

    if ((fd = open(PIDFILE, O_WRONLY|O_CREAT, FILE_MODE)) < 0) {
        qDebug() << "daemon need run by root. open" << PIDFILE << "error.";
        return false;
    }

    if(write_lock(fd, 0, SEEK_SET, 0) < 0)
    {
        if (errno == EACCES || errno == EAGAIN)
            qDebug() << "daemon has been in running!";
        else
            qDebug() << "daemon other error.";
        return false;
    }

    if (ftruncate(fd, 0) < 0) {
        qDebug() << "ftruncate error.";
        return false;
    }

    sprintf(buf,"%d
",getpid()); if (write(fd, buf, strlen(buf)) != strlen(buf)) { qDebug() << "pid write error."; return false; } // close file descriptor if ((val = fcntl(fd, F_GETFD, 0)) < 0) { qDebug() << "fcntl F_GETFD error."; return false; } val |= FD_CLOEXEC; if (fcntl(fd, F_SETFD, val) < 0) { qDebug() << "fcntl F_SETFD error."; return false; } return true; } void initDaemon(void) { pid_t pid, sid; if((pid = fork()) < 0) return; else if(pid != 0) exit(0); /* parent exit */ /* child continues */ sid = setsid(); /* become session leader */ if (sid < 0) { exit(-1); } /* change working directory */ if ((chdir("/")) < 0) { exit(-1); } umask(0); /* clear file mode creation mask */ #if 0 close(0); /* close stdin */ close(1); /* close stdout */ close(2); /* close stderr */ #endif } int main(int argc, char *argv[]) { initDaemon(); if (!isSingleton()) return 0; QCoreApplication a(argc, argv); return a.exec(); }
 
 
3./procディレクトリのプロセス情報を遍歴し、アプリケーションに対応するプロセスが存在する場合は、アプリケーションが実行されているとみなされます.アプリケーションを強制的に閉じ、新しいコマンドラインパラメータで再実行します.このような利点は、簡単な実現であり、私たちの予想した目標に達したことです.欠点はkillの最初の実行インスタンスを強制するのが野蛮で、データが失われる可能性があり、新しいプロセスを作成するオーバーヘッドがユーザーの反応を鈍らせることです.
/*
 * getpid shell: pidof XXX
 * Returns the executable name for given pid.
 */
static gchar *
pid_to_binary_name (gint pid)
{
  gchar * cmd_f;
  FILE  * fcmd;

  if (pid <= 0)
    return NULL;

  cmd_f = g_strdup_printf ("/proc/%d/cmdline", pid);
  fcmd  = fopen (cmd_f, "r");

  g_free (cmd_f);

  if (fcmd)
    {
      gchar buf[256];
      if (fgets (buf, sizeof (buf), fcmd))
        {
          /*
           * 0-terminate at first whitespace.
           */
          gchar *n = &buf[0];
          while ((n < &buf[0] + sizeof(buf) - 1) && *n && !g_ascii_isspace (*n))
            ++n;

          *n = 0;

          return g_path_get_basename (buf);
        }

      fclose (fcmd);
    }

  return NULL;
}
 
4.ウィンドウマネージャにより実現し、アプリケーションのウィンドウに基づいてアプリケーションが実行されているか否かを判断する.対応するアプリケーションがすでに実行されていることに気づいたら、対応するウィンドウを前にします.これはアプリケーションを修正しなければならないので、アプリケーション自身が持っているウィンドウの関係を知っているだけで、アプリケーションのメインウィンドウを前に挙げることを考慮しないと、適切ではありません.この方法は、最初の2つの小さな問題しか解決できません.コマンドラインパラメータは、最初の実行インスタンスに渡されません.
5.アプリケーションはDBUSサービスオブジェクトを提供し、最初の実行インスタンスはサーバとして実行され、2番目の実行インスタンスはクライアントとして実行され、2番目の実行インスタンスはコマンドラインパラメータを最初の実行インスタンスに渡し、終了します.最初の実行インスタンスは、新しいコマンドラインパラメータを受け入れ、対応する処理を行います.たとえば、対応するウィンドウを前述し、コマンドラインパラメータに基づいて処理します.これは第2の方法の改善であり、すべての機能を実現することができ、欠点はアプリケーションを修正することであるが、DBUSサービスオブジェクトは共通ライブラリで実現することができ、アプリケーションの変更は大きくない.
 
6.使用信号量
信号量の知識:
http://www.cublog.cn/u/19185/showart_2034149.html
http://www.ibm.com/developerworks/cn/linux/l-osmig1.html
信号量の例:
#include
#include
#include
#include
#include
#include
#include
#include
#define N 3
pthread_mutex_t mutex_w,mutex_r; //         
sem_t sem_w,sem_r; //        

 int data[N];
int pos=0;
void *function_w(void *arg)
{ 
 int w = *(int *)arg;
 pos = w;
 while(1)
 {
  usleep(100000);
  sem_wait(&sem_w);//        
  pthread_mutex_lock(&mutex_w);//           
  data[pos] = w;
  w++;
  w++;
  w++;
  pos++;
  pos=pos%N;
  pthread_mutex_unlock(&mutex_w);//          
  sem_post(&sem_r);//        
 }
 return (void *)0;
}
void *function_r(void *arg)
{
 while(1)
 {
  sem_wait(&sem_r);//        
  pthread_mutex_lock(&mutex_r);//           
  printf("%d
",data[(pos+N-1)%N]); pthread_mutex_unlock(&mutex_r);// sem_post(&sem_w);// } return (void *)0; } int main(int argc, char **argv) { pthread_t thread[2*N]; int i; pthread_mutex_init(&mutex_w,NULL); pthread_mutex_init(&mutex_r,NULL); sem_init(&sem_w,0,N); sem_init(&sem_r,0,0); for(i=0;i  

 

7. socket , .