【问题标题】:How to send SIGTERM to a process by process name in QNX cpp code?如何通过 QNX cpp 代码中的进程名称将 SIGTERM 发送到进程?
【发布时间】:2015-05-28 22:14:25
【问题描述】:

例如:我有一个名为 foo 的进程。

通常在控制台中,我可以输入 slay foo 然后 foo 终止。 此外,在 cpp 代码中,我可以使用 system("slay foo"); 发出系统调用

我知道 system() 是一个应该避免的繁重的分叉调用。 <csignal><cstdlib>还有其他功能可以选择吗?

我读过 SignalKill() 和 SignalKill_r(),两者都需要我无法提供的 pid。

【问题讨论】:

  • busybox 源代码向您展示了如何执行此操作,或者您可以简单地与 libbb 链接

标签: c++ qnx


【解决方案1】:

这并不像人们想象的那么简单。 Linux 不提供syscall,它通过名称为您提供进程的PID

假设QNXs 文件系统类似于标准 UNI,您可能需要阅读this article 以了解如何使用进程名称查找进程的PID,然后将PIDSignalKill 或@ 一起使用987654328@

这是在 C 中使用进程名称查找进程 PID 的代码。我无法在 QNX 上对其进行测试,但它可以在 Ubuntu 上运行。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <dirent.h>
#include <libgen.h>

/* checks if the string is purely an integer
 * we can do it with `strtol' also
 */
int check_if_number (char *str)
{
  int i;
  for (i=0; str[i] != '\0'; i++)
  {
    if (!isdigit (str[i]))
    {
      return 0;
    }
  }
  return 1;
}

#define MAX_BUF 1024
#define PID_LIST_BLOCK 32

int *pidof (char *pname)
{
  DIR *dirp;
  FILE *fp;
  struct dirent *entry;
  int *pidlist, pidlist_index = 0, pidlist_realloc_count = 1;
  char path[MAX_BUF], read_buf[MAX_BUF];

  dirp = opendir ("/proc/");
  if (dirp == NULL)
  {
    perror ("Fail");
    return NULL;
  }

  pidlist = malloc (sizeof (int) * PID_LIST_BLOCK);
  if (pidlist == NULL)
  {
    return NULL;
  }

  while ((entry = readdir (dirp)) != NULL)
  {
    if (check_if_number (entry->d_name))
    {
      strcpy (path, "/proc/");
      strcat (path, entry->d_name);
      strcat (path, "/comm");

      /* A file may not exist, it may have been removed.
       * dut to termination of the process. Actually we need to
       * make sure the error is actually file does not exist to
       * be accurate.
       */
      fp = fopen (path, "r");
      if (fp != NULL)
      {
        fscanf (fp, "%s", read_buf);
        if (strcmp (read_buf, pname) == 0)
        {
          /* add to list and expand list if needed */
          pidlist[pidlist_index++] = atoi (entry->d_name);
          if (pidlist_index == PID_LIST_BLOCK * pidlist_realloc_count)
          {
            pidlist_realloc_count++;
            pidlist = realloc (pidlist, sizeof (int) * PID_LIST_BLOCK * pidlist_realloc_count); //Error check todo
            if (pidlist == NULL)
            {
              return NULL;
            }
          }
        }
        fclose (fp);
      }
    }
  }


  closedir (dirp);
  pidlist[pidlist_index] = -1; /* indicates end of list */
  return pidlist;
}

int main (int argc, char *argv[])
{
  int *list, i;

  if (argc != 2)
  {
    printf ("Usage: %s proc_name\n", argv[0]);
    return 0;
  }
  list = pidof (argv[1]);
  for (i=0; list[i] != -1; i++)
  {
    printf ("%d ", list[i]);
  }
  free (list);
  if (list[0] != -1)
  {
    printf ("\n");
  }
  return 0;
}

【讨论】:

  • 如果需要这么多工作(打开目录和文件等),那么您不妨使用 system("slay foo")
  • @ooga 谁说slay 更有效率?我不知道有任何qnx API 可以让它更快
  • 谢谢,效果很好!我想知道为什么 QNX 不提供系统调用来返回这样的东西。
【解决方案2】:

为了将进程名称转换为 pid,您需要深入了解 QNX 的 /proc 文件系统。我写了一本名为“QNX Cookbook”的书,现在可以在 QNX 的网站 (http://www.qnx.com/download/feature.html?programid=26184) 上免费在线获取。转到第 222 页,“遍历进程列表”并复制遍历进程列表的代码。这将允许您在所有进程中搜索您想要杀死的任何进程(它会为您提供所需的 PID)。

void
iterate_processes (void)
{
  struct dirent   *dirent;
  DIR             *dir;
  int             r;
  int             pid;

  // 1) find all processes
  if (!(dir = opendir ("/proc"))) {
    fprintf (stderr, "%s:  couldn't open /proc, errno %d\n",
             progname, errno);
    perror (NULL);
    exit (EXIT_FAILURE);
  }

  while (dirent = readdir (dir)) {
    // 2) we are only interested in process IDs
    if (isdigit (*dirent -> d_name)) {
      pid = atoi (dirent -> d_name);
      iterate_process (pid);
    }
  }
  closedir (dir);
}

void
iterate_process (int pid)
{
  char      paths [PATH_MAX];
  int       fd;

  // 1) set up structure
  static struct {
    procfs_debuginfo    info;
    char                buff [PATH_MAX];
  } name;

  sprintf (paths, "/proc/%d/as", pid);

  if ((fd = open (paths, O_RDONLY)) == -1) {
    return;
  }

  // 2) ask for the name
  if (devctl (fd, DCMD_PROC_MAPDEBUG_BASE, &name,
              sizeof (name), 0) != EOK) {
    if (pid == 1) {
      strcpy (name.info.path, "(procnto)");
    } else {
      strcpy (name.info.path, "(n/a)");
    }
  }

  // 3) we can compare against name.info.path here...
  do_process (pid, fd, name.info.path);
  close (fd);
}

通过为“do_process()”提供你想要的任何操作,你可以例如按名字杀死等等。

【讨论】:

    猜你喜欢
    • 2021-08-21
    • 2010-12-03
    • 1970-01-01
    • 1970-01-01
    • 2017-10-02
    • 1970-01-01
    • 1970-01-01
    • 2015-01-28
    • 1970-01-01
    相关资源
    最近更新 更多