程序实现思想:
Linux 系统的进程号是保存在 /proc 目录下的,一个在 linux 系统上运行得程序,只要是在运行状态下,就必然会再 /proc 目录下写入一批文件,其文件写入的方式如下:
/proc/<进程ID>/文件组
这里面的文件组是指一批文件,不是指一个文件,大致的文件名信息如下:
dr-xr-xr-x 2 work work 0 09-21 00:51 attr
-r-------- 1 work work 0 09-21 00:51 auxv
-r--r--r-- 1 work work 0 09-21 00:51 cmdline
-rw-r--r-- 1 work work 0 09-21 00:51 coredump_filter
-r--r--r-- 1 work work 0 09-21 00:51 cpuset
lrwxrwxrwx 1 work work 0 09-21 00:51 cwd -> /home/work/tmp
-r-------- 1 work work 0 09-21 00:51 environ
lrwxrwxrwx 1 work work 0 09-21 00:51 exe -> /home/work/tmp/tt
dr-x------ 2 work work 0 09-21 00:51 fd
dr-x------ 2 work work 0 09-21 00:51 fdinfo
-r-------- 1 work work 0 09-21 00:51 io
-r--r--r-- 1 work work 0 09-21 00:51 limits
-rw-r--r-- 1 work work 0 09-21 00:51 loginuid
-r--r--r-- 1 work work 0 09-21 00:51 maps
-rw------- 1 work work 0 09-21 00:51 mem
-r--r--r-- 1 work work 0 09-21 00:51 mounts
-r-------- 1 work work 0 09-21 00:51 mountstats
-r--r--r-- 1 work work 0 09-21 00:51 numa_maps
-rw-r--r-- 1 work work 0 09-21 00:51 oom_adj
-r--r--r-- 1 work work 0 09-21 00:51 oom_score
lrwxrwxrwx 1 work work 0 09-21 00:51 root -> /
-r--r--r-- 1 work work 0 09-21 00:51 schedstat
-r--r--r-- 1 work work 0 09-21 00:51 smaps
-r--r--r-- 1 work work 0 09-21 00:51 stat
-r--r--r-- 1 work work 0 09-21 00:51 statm
-r--r--r-- 1 work work 0 09-21 00:51 status
dr-xr-xr-x 3 work work 0 09-21 00:51 task
-r--r--r-- 1 work work 0 09-21 00:51 wchan
比如,我们运行了一个程序 tt ,假设其进程号为 31673 ,则在 /proc 目录下会形成 /proc/31673/ 的目录,且在其目录下存在上述的文件组。这个里面,我们需要的文件为 status ,该文件保存的是 tt 当前运行得状态,我们来看看这个文件的内容:
Name: tt
State: S (sleeping)
SleepAVG: 98%
Tgid: 31673
Pid: 31673
PPid: 7977
TracerPid: 0
Uid: 500 500 500 500
Gid: 500 500 500 500
FDSize: 256
Groups: 500
VmPeak: 3828 kB
VmSize: 3664 kB
VmLck: 0 kB
VmHWM: 300 kB
VmRSS: 300 kB
VmData: 44 kB
VmStk: 88 kB
VmExe: 4 kB
VmLib: 1448 kB
VmPTE: 32 kB
StaBrk: 09e04000 kB
Brk: 09e04000 kB
StaStk: 7ffff0e895d0 kB
Threads: 1
SigQ: 0/8192
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000000
SigCgt: 0000000000000000
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
Cpus_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,ffffffff
Mems_allowed: 00000000,00000001
我们发现,这个文件的第一行就是文件名,有了这个东西,那我们就有了获取当前正在运行得特定程序的进程号了。
基本的解决思路是,我们通过遍历 /proc 目录下所有的用数字作为目录的子目录,依次打开这些目录下的 status 文件,获取其中的第一行内容,并从中获取对应的 Name 节的信息,与我们传入的需要查询的程序名字进行比较,如果一致,则该目录的数字就是该程序的进程号。
/* find_pid_by_name()
*
* This finds the pid of the specified process.
* Currently, it's implemented by rummaging through
* the proc filesystem.
* Returns a list of all matching PIDs
*/
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define READ_BUF_SIZE 1024
long* find_pid_by_name( char* pidName)
{
DIR *dir;
struct dirent *next;
long* pidList=NULL;
int i=0;
dir = opendir("/proc");
if (!dir)
{
//perror_msg_and_die("Cannot open /proc");
fprintf(stderr, "Cannot open /proc\n");
return pidList;
}
while ((next = readdir(dir)) != NULL)
{
FILE *status;
char filename[READ_BUF_SIZE];
char buffer[READ_BUF_SIZE];
char name[READ_BUF_SIZE];
/* Must skip ".." since that is outside /proc */
if (strcmp(next->d_name, "..") == 0)
continue;
/* If it isn't a number, we don't want it */
if (!isdigit(*next->d_name))
continue;
sprintf(filename, "/proc/%s/status", next->d_name);
if (! (status = fopen(filename, "r")) )
{
continue;
}
//Read first line in /proc/?pid?/status
if (fgets(buffer, READ_BUF_SIZE-1, status) == NULL)
{
fclose(status);
continue;
}
fclose(status);
// Buffer should contain a string like "Name: binary_name"a
sscanf(buffer, "%*s %s", name);
if ( name != NULL && name[0] != '\0')
{
if (strcmp(name, pidName) == 0)
{
pidList=realloc( pidList, sizeof(long) * (i+2));
pidList[i++]=strtol(next->d_name, NULL, 0);
}
}
}
if (pidList)
{
pidList[i]=0;
}
return pidList;
}
int main ( int argc , char **argv)
{
long *pid_t=NULL;
if ( argc != 2 )
{
fprintf(stdout,"Usage %s <filename>\n",argv[0]);
return 0;
}
pid_t = find_pid_by_name( argv[1]);
while ( pid_t != 0 && *pid_t != 0)
{
fprintf(stdout,"\n%s is [ %d]\n",argv[1],*pid_t);
pid_t++;
}
return 0;
}
这段程序中特别需要注意的是:
main 函数中的 while(pid_t != 0 && *pid_t != 0) 这一行,开始的时候俺没有注意,一直报段错误,仔细观察后发现,不仅需要判断这个指针的值是否是等于 0 , 同时还得判断这个指针本身是否等于 0 ,否则会出现查询的程序根本就没有运行时出现段错误,或者是查询的程序运行了,也会出现段错误的情况。
==============================================
此程序在需要限制某些程序在特定的时间内只能一次运行的情况下很有好处,这种情况多数出现在金融系统、保险系统、收费系统等核心业务领域,通常在日终账务处理时,绝对不允许在同一个时间内连续两次运行扎帐程序,否则会造成业务数据紊乱。
因此,我们可以在程序运行得时候,首先获取自身的进程号 pid (用 getpid()函数获取),然后通过上述的程序代码,获取当前程序的进程号,如果存在两个,则退出当前的程序,从而保证在一个特定的时间内,扎帐程序只有一个运行。
分享到:
相关推荐
1. **进程Name**:每个运行的程序在操作系统中都有一个唯一的进程名,它标识了正在执行的进程。 2. **进程ID**:进程ID(PID)是操作系统分配给进程的一个唯一数字,用于区分系统中的不同进程。 3. **模块**:在...
首先,我们需要理解的是,C语言本身并不直接提供获取程序运行时间的函数。但是,我们可以借助操作系统提供的接口或者标准库中的函数来实现这一目标。在大多数Unix和类Unix系统(包括Linux)中,可以使用`<time.h>`...
"C语言多进程多线程编程" ...在UNIX系统中,多进程编程是非常常见的,UNIX系统本身就是用C语言写的多进程程序。多进程编程可以提高系统的并发性和性能,但是也需要注意进程同步和进程通信的问题。
在IT领域,C语言是一种基础且强大的编程语言,被广泛应用于系统编程、嵌入式开发以及各种软件开发中。"查杀进程"是系统管理的一部分,涉及到操作系统内核的交互和进程控制。在这个主题中,我们将深入探讨如何使用...
总的来说,理解和掌握Linux系统下C语言编程中的进程创建和管理是开发高效、安全的系统级程序的基础。这涉及到进程的生命周期、状态转换、标识符、权限控制以及进程间的通信等多个方面。通过对这些概念和技术的深入...
在IT领域,获取PC当前运行进程的全路径是一项基础但重要的任务,这通常涉及到系统监控、性能分析或者软件调试。本项目是利用Visual Studio 2008(VS2008)进行开发的,旨在提供一个工具或方法来获取操作系统中所有...
C语言多进程多线程编程概述 多进程编程是计算机系统中的一种重要机制,通过创建多个进程来实现程序的并发执行,提高系统的效率和性能。在C语言中,多进程编程通过系统调用来实现,系统调用fork()可以创建一个新的...
### Linux下C语言编程——进程的创建 #### 一、进程的概念 在现代操作系统中,程序与进程是两个重要的概念。程序是指一个包含了可执行代码的文件,它本身是静态的,而进程则是指已经开始执行但尚未结束的程序实例...
Process类代表一个正在运行的进程,而ProcessManager类则提供了访问系统进程的全局方法。以下是一些关键步骤: 1. **获取所有运行进程**:可以使用Process.GetProcesses()方法获取当前计算机上运行的所有进程列表。...
### C语言多进程多线程编程相关知识点 #### 进程与线程的基本概念 - **进程**: 进程是一个程序在计算机上的一次执行活动。它是系统进行资源分配和调度的基本单位,拥有独立的地址空间和其他资源。进程之间相互独立...
在QT编程中,为了实现对系统的深入监控,如获取进程信息、硬件状态以及进行设备管理,我们可以利用QT库提供的QProcess、QFile、QDir、QFileSystemWatcher等类。以下将详细阐述如何利用这些工具来实现标题和描述中...
在VB(Visual Basic)编程中,检测一个程序是否在运行或者一个文件是否正在被占用是一项常见的任务,这对于实现某些功能,比如防止多个实例同时运行、管理文件操作等至关重要。下面我们将详细探讨如何在VB中实现这些...
在IT领域,C语言是一种基础且强大的...总结来说,这个C语言项目涵盖了Windows API的使用、进程管理以及用户界面交互等多个方面,对于学习和提升C语言编程能力,特别是在系统级编程上的应用,是非常有价值的实践案例。
4. **编程接口**:在C/C++中,可以使用`getpid()`函数获取当前进程的PID,而`pgrep`或`kill`命令可以查找特定名字的进程并返回其PID。 在编程环境中,如Python、Java、Ruby等,也有相应的库或函数可以获取进程ID。...
在Windows操作系统中,获取某个进程的主窗口以及创建该进程的程序名是常见的系统编程任务,这涉及到进程管理和窗口句柄操作。以下是如何实现这一功能的详细步骤。 首先,我们需要理解“进程”这个概念。在计算机...
标题 "在SYSTEM权限下以当前用户权限运行程序" 涉及的是计算机系统中的权限管理和程序执行的概念。在Windows操作系统中,权限分为不同级别,其中SYSTEM权限是最高的,它允许程序访问系统的核心资源,包括硬件、...
学习Linux进程控制编程不仅有助于理解系统的运行机制,也对于开发系统级软件、服务器程序和嵌入式系统至关重要。在实际开发中,掌握这些基本的进程控制技术能有效提高程序的稳定性和可维护性。通过阅读书籍如《基于...
每个进程在运行时都会打印其进程号,以此来标识其在进程树中的位置。 第二部分的编程任务涉及到了管道通信。管道是一种简单的半双工通信机制,数据只能单向流动。在这个例子中,父进程创建一个管道,然后将一个字符...