プログラムインスタンスが実行されたか否かを判断するN種類の方法
6077 ワード
1.作成したファイルにプロセスIDを書き込み、機械が正常に終了していない場合は、再起動後にこのファイルを読み取り、プロセスIDを取得し、IDに基づいてプロセスが実行中かどうかを判定し、そうでない場合はファイルを削除する.これにより、ファイルを削除せず、プログラムが実行できないという問題は発生しません.
2.ファイルを開き、ロックします.新しく実行したプログラムは、ファイルを再度ロックしようとしますが、ロックされているため、エラーメッセージが返されます.これにより,プログラムが実行されたか否かを判断できる.FD_の設定CLOEXEC後、プログラムが終了する限り、再度ロックできます.通常、スプライトプロセスではapacheなどの方法が使用され、デフォルトでは/var/runディレクトリにあります.
3./procディレクトリのプロセス情報を遍歴し、アプリケーションに対応するプロセスが存在する場合は、アプリケーションが実行されているとみなされます.アプリケーションを強制的に閉じ、新しいコマンドラインパラメータで再実行します.このような利点は、簡単な実現であり、私たちの予想した目標に達したことです.欠点はkillの最初の実行インスタンスを強制するのが野蛮で、データが失われる可能性があり、新しいプロセスを作成するオーバーヘッドがユーザーの反応を鈍らせることです.
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
信号量の例:
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 , .