`
telyy123
  • 浏览: 13067 次
  • 性别: Icon_minigender_1
  • 来自: 湖北
最近访客 更多访客>>
社区版块
存档分类
最新评论

C 编程获取正在运行的程序进程号

 
阅读更多
程序实现思想:
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()函数获取),然后通过上述的程序代码,获取当前程序的进程号,如果存在两个,则退出当前的程序,从而保证在一个特定的时间内,扎帐程序只有一个运行。
分享到:
评论

相关推荐

    《Windows网络编程技术》高清PDF版+随书源码

    第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个实例源码2012813

    C#与进程有关的3个实例源码 程序介绍: 3个与进程有关的C#源码...进程管理器、获取当前正在运行的所有进程、使用进程加载外部应用程序等, 每一个实例源代码都与Windows进程紧密相关,是进程相关编程的实用参考资料。

    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 参考文献 ...

    Tcl_TK编程权威指南pdf

    使用exec运行程序 file命令 跨平台的文件命名方式 操作文件和目录 文件属性 对i/o命令的总结 打开文件用于i/o操作 读写操作 当前目录-cd和pwd 使用glob来匹配文件名 exit和pid命令 环境变量 registry...

    Visual C++编程技巧精选500例.pdf

    264 如何设置系统启动自运行程序? 265 如何在程序中将其他窗口程序调至前台? 266 如何获取当前系统时间? 267 如何设置当前系统时间? 268 如何计算时间差? 269 如何获取系统显示元素的颜色? 270 如何获取系统当前的...

    系统相关的实例50个

    C语言编程宝典 C++语言开发的日期处理类库 C语言模块检查 DES 加密系统的 C 语言源代码 封装了NT下底层安全功能的类 DirectDraw扩展类 封装PDH功能的MFC类 IL2HDK31 HTTP服务器源代码 飞机订票系统课程设计源代码 ...

    精通Windows.API-函数、接口、编程实例.pdf

    6.5.4 运行时动态获取DLL导出函数地址并调用 189 6.5.5 声明导出函数、创建lib库,为其他模块提供导入表调用接口 190 6.5.6 通过构建导入表调用DLL导出函数 191 第7章 线程同步 192 7.1 基本原理 192 ...

    PERL语言编程

    不过,随后 Perl 就开始风行,于是它就成了可以操作文件系统,进程管理,数据库管理,进行 C/S 编程和安全编程,web 信息管理,甚至可以进行面向对象和面向功能的编程的语言。而且这些功能并非只是在 Perl 这边,每...

    WINDOWS网络编程技术.pdf

    第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 应用...

    精通WindowsAPI 函数 接口 编程实例

    6.5.4 运行时动态获取DLL导出函数地址并调用 189 6.5.5 声明导出函数、创建lib库,为其他模块提供导入表调用接口 190 6.5.6 通过构建导入表调用DLL导出函数 191 第7章 线程同步 192 7.1 基本原理 192 ...

    网络编程教程,很好的一本写linux网络编程书,这是我上传的源码

     8.1.6 通过端口号获取服务名  8.2 套接字选项  8.2.1 获取和设置套接字选项  8.2.2 通用套接字选项  本章小结 第三篇 应用提高篇  第九章 高级套接字函数编程实践  9.1 函数recv和send  ...

    VISUAL BASIC 编程标准

    本书是讲述Visual Basic编程标准的一本专著。全书分5个部分,共14章。分别讲述使用Visual Basic编程时总体设计、代码结构设计、用户界面设计和小组软件开发应遵循的标准。全书配有大量应用实例,便于读者学以致用。...

    linux programming instances网络编程教程 附源代码

    本书通过55个精彩的实例,全面剖析了在Linux下编写网络应用程序的方法,并阐述了网络协议架构和开发规范。为了适应不同读者的需要,本书从最基本的Linux系统操作到网络技术的基本理念,逐步深入至...3.在gdb下运行程序

    Python编程入门经典

    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 ...

    Access+2000中文版高级编程

    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...

    实验三-进程通讯实验报告.doc

    【实验内容】 设计一个多进程并发运行的程序,它由不同的进程完成下列工作: (1)接收键盘输入进程 负责接收用户的键盘输入,并以适当的方式将由键盘获得的数据交给其它进程处理。 (2)显示进程 负责全部数据显示...

    实验三-进程通讯实验报告.pdf

    【实验内容】 设计一个多进程并发运行的程序,它由不同的进程完成下列工作: (1)接收键盘输入进程 负责接收用户的键盘输入,并以适当的方式将由键盘获得的数据交 给其它进程处理。 (2)显示进程 负责全部数据...

    linux大作业报告

    1、编写程序,获取并输出子进程和父进程的相关信息。 2、编写程序,要求用户设计多进程应用程序,改程序作为父进程执行,在执行过程中能够通过调用自身创建一个子进程。父进程和子进程均在终端中输出一条信息,标识...

Global site tag (gtag.js) - Google Analytics