程序实现思想:
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章 Windows网络编程基础1.1 Windows网络应用1.1.1 常用的网络应用实例1.1.2 网络应用的特点与运行环境1.1.3 网络应用前景1.2 Windows环境下的应用程序1.2.1 应用程序的形态1.2.2 应用程序的运行环境1.2.3 应用...
C#与进程有关的3个实例源码 程序介绍: 3个与进程有关的C#源码...进程管理器、获取当前正在运行的所有进程、使用进程加载外部应用程序等, 每一个实例源代码都与Windows进程紧密相关,是进程相关编程的实用参考资料。
8.2.2 如何使用C/C++语言提取可执行程序代码 179 8.3 如何对PE文件加壳 182 8.3.1 PE文件的加壳方法 182 8.3.2 向PE文件中静态注入代码的完整实例 183 8.4 如何实现文件脱壳 191 8.5 本章小结 192 参考文献 ...
使用exec运行程序 file命令 跨平台的文件命名方式 操作文件和目录 文件属性 对i/o命令的总结 打开文件用于i/o操作 读写操作 当前目录-cd和pwd 使用glob来匹配文件名 exit和pid命令 环境变量 registry...
264 如何设置系统启动自运行程序? 265 如何在程序中将其他窗口程序调至前台? 266 如何获取当前系统时间? 267 如何设置当前系统时间? 268 如何计算时间差? 269 如何获取系统显示元素的颜色? 270 如何获取系统当前的...
C语言编程宝典 C++语言开发的日期处理类库 C语言模块检查 DES 加密系统的 C 语言源代码 封装了NT下底层安全功能的类 DirectDraw扩展类 封装PDH功能的MFC类 IL2HDK31 HTTP服务器源代码 飞机订票系统课程设计源代码 ...
6.5.4 运行时动态获取DLL导出函数地址并调用 189 6.5.5 声明导出函数、创建lib库,为其他模块提供导入表调用接口 190 6.5.6 通过构建导入表调用DLL导出函数 191 第7章 线程同步 192 7.1 基本原理 192 ...
不过,随后 Perl 就开始风行,于是它就成了可以操作文件系统,进程管理,数据库管理,进行 C/S 编程和安全编程,web 信息管理,甚至可以进行面向对象和面向功能的编程的语言。而且这些功能并非只是在 Perl 这边,每...
第1章 Windows网络编程基础1.1 Windows网络应用1.1.1 常用的网络应用实例1.1.2 网络应用的特点与运行环境1.1.3 网络应用前景1.2 Windows环境下的应用程序1.2.1 应用程序的形态1.2.2 应用程序的运行环境1.2.3 应用...
6.5.4 运行时动态获取DLL导出函数地址并调用 189 6.5.5 声明导出函数、创建lib库,为其他模块提供导入表调用接口 190 6.5.6 通过构建导入表调用DLL导出函数 191 第7章 线程同步 192 7.1 基本原理 192 ...
8.1.6 通过端口号获取服务名 8.2 套接字选项 8.2.1 获取和设置套接字选项 8.2.2 通用套接字选项 本章小结 第三篇 应用提高篇 第九章 高级套接字函数编程实践 9.1 函数recv和send ...
本书是讲述Visual Basic编程标准的一本专著。全书分5个部分,共14章。分别讲述使用Visual Basic编程时总体设计、代码结构设计、用户界面设计和小组软件开发应遵循的标准。全书配有大量应用实例,便于读者学以致用。...
本书通过55个精彩的实例,全面剖析了在Linux下编写网络应用程序的方法,并阐述了网络协议架构和开发规范。为了适应不同读者的需要,本书从最基本的Linux系统操作到网络技术的基本理念,逐步深入至...3.在gdb下运行程序
10.4.5 将模块作为程序运行 165 10.5 创建一个完整的模块 166 10.6 安装模块 171 10.7 本章小结 174 10.8 习题 175 第11章 文本处理 177 11.1 文本处理的用途 177 11.1.1 搜索文件 178 11.1.2 日志剪辑 179 11.1.3 ...
13.4 应用自动化功能从Access运行其他应用程序 395 13.4.1 在Access中调用Word 396 13.4.2 在Access中调用Excel 402 13.4.3 在Access中调用Microsoft Graph 404 13.4.4 在Access中调用Microsoft Project 407...
【实验内容】 设计一个多进程并发运行的程序,它由不同的进程完成下列工作: (1)接收键盘输入进程 负责接收用户的键盘输入,并以适当的方式将由键盘获得的数据交给其它进程处理。 (2)显示进程 负责全部数据显示...
【实验内容】 设计一个多进程并发运行的程序,它由不同的进程完成下列工作: (1)接收键盘输入进程 负责接收用户的键盘输入,并以适当的方式将由键盘获得的数据交 给其它进程处理。 (2)显示进程 负责全部数据...
1、编写程序,获取并输出子进程和父进程的相关信息。 2、编写程序,要求用户设计多进程应用程序,改程序作为父进程执行,在执行过程中能够通过调用自身创建一个子进程。父进程和子进程均在终端中输出一条信息,标识...