AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 748487
Accepted
joseph lake
joseph lake
Asked: 2023-06-10 17:03:35 +0800 CST2023-06-10 17:03:35 +0800 CST 2023-06-10 17:03:35 +0800 CST

verifique se o processo está ativo do PID durante o manuseio do PID reciclado

  • 772

Pelo que vi online você chama o método kill em c++ para ver se o processo está vivo. o problema com isso é que os PIDs são rycleados e o mesmo PID que você está procurando pode não ser o mesmo processo. Eu tenho um programa que possui dois processos que não são filhos um do outro. A única maneira de se comunicar com eles é IPC. Eu gostaria que meu processo de host fosse encerrado quando o processo do cliente fosse encerrado. Para fazer isso, preciso saber quando o processo do cliente não está mais ativo.

No Windows, eles têm o que é chamado de manipulador de processo que reservará o PID de ser reciclado até que o processo que criou o identificador seja encerrado. Estou me perguntando como conseguir isso para sistemas macOS/Linux (POSIX).

O código problemático como PIDs são reciclados.

if (0 == kill(pid, 0))
{
    // Process exists.
}
process
  • 2 2 respostas
  • 53 Views

2 respostas

  • Voted
  1. Marcus Müller
    2023-06-10T17:44:43+08:002023-06-10T17:44:43+08:00

    Pelo que vi online você chama o método kill em c++ para ver se o processo está vivo. o problema com isso é que os PIDs são rycleados e o mesmo PID que você está procurando pode não ser o mesmo processo

    Exatamente, então essa killabordagem não funciona. Realmente, fim da história aí. Não é uma ferramenta de trabalho para isso.

    Duas opções:

    • se o processo que você está assistindo for seu processo filho (ou no grupo de processos do seu próprio processo), waitpiddestina-se exatamente a assistir quando sair
    • se o processo não for seu processo filho, os "ideais" do POSIX meio que sugerem que seu próprio processo não tem nenhum negócio interagindo fortemente com o tempo de vida desse processo (pelo menos essa é a minha opinião sobre as limitações do waitpid). Você pode esperar ter privilégios de "rastreamento" e usar ptracepara anexar a outro processo e aguardar exitchamadas.
    • 0
  2. Best Answer
    joseph lake
    2023-06-13T12:03:54+08:002023-06-13T12:03:54+08:00

    A solução é reservar o PID no Windows armazenando em cache e não fechando o arquivo process handle. Para POSIXsistemas, simplesmente obtemos a hora de início do processo do kernal OS DEPENDANT! e, em seguida, verificamos se a hora de início armazenada em cache é igual à hora de início atual. Se não, um conflito de PID é detectado e retorna falso.

    Janelas:

    #include <windows.h>
    #include <iostream>
    #include <vector>
    #include <map>
    
    map<DWORD, HANDLE> handles;
    bool isProcessAlive(DWORD pid)
    {
        HANDLE process;
        if(handles.find(pid) == handles.end())
        {
            process = OpenProcess(SYNCHRONIZE, FALSE, pid);
            handles[pid] = process;
        }
        else
        {
            process = handles[pid];
        }
        DWORD ret = WaitForSingleObject(process, 0);
        bool isRunning = ret == WAIT_TIMEOUT;
        if(!isRunning)//close the cached handle to free the PID and erase from the cache
        {
            CloseHandle(process);
            handles.erase(pid);
        }
        return isRunning;
    }
    

    Mac OS:

    #include <signal.h>
    #include <stddef.h>
    #include <sys/_types/_timeval.h>
    #include <sys/errno.h>
    #include <sys/proc.h>
    #include <sys/sysctl.h>
    #include <cstring>
    #include <iostream>
    #include <map>
    #include <string>
    /**
     * map of unsigned long, creation time either in jiffies, ms, or in clock ticks or different on mac even. so we keep it as a string
     */
    std::map<unsigned long, string> handles;
    /**
     * returns true if the process is alive and attempts to suggest a handle to linux's os that we are reading the directory /proc/[PID] reserve this PID till program shutdown
     */
    bool isProcessAlive(unsigned long pid)
    {
        // Get process info from kernel
        struct kinfo_proc info;
        int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, (int)pid };
        size_t len = sizeof info;
        memset(&info,0,len);
        int rc = sysctl(mib, (sizeof(mib)/sizeof(int)), &info, &len, NULL, 0);
    
        //exit program sysctl failed to verify PID
        if (rc != 0)
        {
            handles.erase(pid);
            return false;
        }
    
        //extract start time and confirm PID start time equals org start time
        struct timeval tv = info.kp_proc.p_starttime;
        if(tv.tv_sec == 0)
        {
            handles.erase(pid);
            return false;
        }
        string time = to_string(tv.tv_usec) + "-" + to_string(tv.tv_sec);
        if(handles.find(pid) != handles.end())
        {
            string org_time = handles[pid];
            if(org_time != time)
            {
                cout << "PID Conflict PID:" << pid << " org_time:" + org_time << " new_time:" << time << endl;
                handles.erase(pid);
                return false;
            }
        }
        else
        {
            handles[pid] = time;
        }
        return true;
    }
    

    Linux:

    #include <iostream>
    #include <vector>
    #include <map>
    #include <signal.h>
    #include <dirent.h>
    #include <errno.h>
    #include <fstream>
    
    #include <iostream>
    #include <iterator>
    #include <sstream>
    #include <fstream>
    #include <vector>
    #include <cstring>
    #include <cerrno>
    #include <ctime>
    #include <cstdio>
    #include <fcntl.h>
    #include <sys/time.h>
    
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <string>
    #include "/usr/include/x86_64-linux-gnu/sys/param.h"
    
    /**
     * map of unsigned long, creation time either in jiffies, ms, or in clock ticks or different on mac even. so we keep it as a string
     */
    std::map<unsigned long, string> handles = {};
    /**
     * returns true if the process is alive and attempts to suggest a handle to linux's os that we are reading the directory /proc/[PID] reserve this PID till program shutdown
     */
    bool isProcessAlive(unsigned long pid)
    {
        ifstream procFile;
        string f = "/proc/"+ std::to_string(pid)+ "/stat";
        procFile.open(f.c_str());
        if(!procFile.fail())
        {
            //get creation time of current pid's process
            char str[255];
            procFile.getline(str, 255);  // delim defaults to '\n'
    
            vector<string> tmp;
            istringstream iss(str);
            copy(istream_iterator<string>(iss),
                 istream_iterator<string>(),
                 back_inserter<vector<string> >(tmp));
    
            string creation_time = tmp.at(21);
    
            //check if the process's creation time matches the cached creation time
            if(handles.find(pid) != handles.end())
            {
                string org = handles[pid];
                //if the pid's creation time is not the cached creation time we assume it's not the same process and the original has closed
                //unlike java the ==,!= actually checks .equals() when comparing
                if(creation_time != org)
                {
                    std::cerr << "PID conflict:" + to_string(pid) + " orgCreationTime:" + org + " newCreationTime:" + creation_time;
                    handles.erase(pid);
                    procFile.close();
                    return false;
                }
            }
            handles[pid] = creation_time;
            procFile.close();
            return true;
        }
        handles.erase(pid);
        procFile.close();
        return false;
    }
    
    • 0

relate perguntas

  • Como substituir os IDs de usuário e IDs de grupo por nomes em vez de números em "ps"?

  • Como obter os IDs dos grupos suplementares de um processo?

  • O que `/proc/irq/.../spurious` contém?

  • Um processo pai pode alterar o ambiente de seu filho?

  • Como 'ejetar' obtém processos para fechar identificadores de arquivo?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve