Desenvolvimento multiplataforma (Linux) baseado em VS2019 C++ (1.4.2) - com sinais de parâmetro

Continuando com o artigo anterior, este capítulo aprenderá primeiro sobre sinais com parâmetros e funções como sigqueue e sigaction

Desenvolvimento multiplataforma (Linux) baseado em VS2019 C++ (1.4) - Signal

I. Introdução

A função kill que mencionamos no último artigo envia um sinal apenas para um determinado processo e não reflete os parâmetros. Também foi mencionado anteriormente que o compartilhamento de dados não pode ser realizado no processo, mesmo que uma variável global seja definida e modificada entre processos filho, o processo pai não sabe se foi modificado ou não. Portanto, esta situação requer comunicação IPC para resolver, e kill não pode transmitir dados, então você precisa usar um sinal com parâmetros

2. Protótipo de função

1. função da biblioteca sigaction - sinal de ligação

Função: Usada para alterar o comportamento de um processo após receber um sinal específico.

Arquivo de cabeçalho <signal.h>

原型: int sigaction(int signum,const struct sigaction *act,const struct sigaction *old);

parâmetro

  • O primeiro parâmetro é o valor do sinal, que pode ser qualquer sinal válido específico, exceto sigkill e sigstop (defina sua própria função de processamento para esses dois sinais, o que resultará em um erro de instalação do sinal)
  • O segundo parâmetro é um ponteiro para uma instância da estrutura sigaction. Na instância da estrutura sigaction, o processamento de um sinal específico é especificado. Ele pode estar vazio, e o processo processará o sinal por padrão.
  • O objeto apontado pelo terceiro parâmetro oldact é usado para salvar o processamento original do sinal correspondente, geralmente null .

Nota: Os parâmetros dois e três são ponteiros para estruturas. O segundo parâmetro é o mais importante . A função de processamento de sinal está incluída nesta estrutura, mas a função não pode ser atribuída diretamente ao segundo parâmetro quando é usada.

Valor de retorno: A função retorna 0 em caso de sucesso, -1 em caso de falha

Veja a função sigaction no linux da seguinte forma

A estrutura do segundo parâmetro correspondente seguection é a seguinte

        Não pode haver uma função na estrutura c, mas aqui apenas o ponteiro de função é reservado, e isso não quebra a estipulação de que não pode haver uma função na estrutura. Para a estrutura, é apenas uma variável de ponteiro (mais especial, apontando para uma função)

        A primeira é semelhante ao ponteiro de função sem parâmetros mencionados acima, então usamos a segunda função para implementar o sinal com parâmetros e, em seguida, usamos sa_flags para determinar se ele possui parâmetros

2, função de biblioteca sigqueue - enviar sinal

Função: A nova chamada de sistema para envio de sinais, principalmente para sinais em tempo real, suporta sinais com parâmetros e é usada em pares com a função sigaction().

Valor: int sigqueue(pid_t pid, int sig, const union sigval value);

parâmetro  

  • O primeiro parâmetro é o id do processo que especifica o sinal de recebimento
  • O segundo parâmetro determina o sinal que está prestes a ser enviado
  • O terceiro parâmetro é uma estrutura de dados union sigval (semelhante à estrutura, raramente usada), que especifica os parâmetros passados ​​pelo sinal, ou seja, o chamado valor de 4 bytes.

Valor de retorno: 0 para sucesso, -1 para falha

Veja a função sigqueue no linux da seguinte forma 

A união sigval correspondente do segundo parâmetro é a seguinte 

 Onde sigval_int são os dados inteiros a serem enviados

3. Realização

1. Código de exemplo

Este exemplo implementa o processo pai para enviar sinais e passar dados para o processo filho

①O void signalFunc(int i) anterior é adequado apenas para o uso de sinais sem parâmetro, portanto, a função redefinida é a seguinte

void sigaction_func(int num, siginfo_t* info, void* vo)

O primeiro número do parâmetro é o código do sinal recebido e os dados recebidos são armazenados nas informações do segundo parâmetro

② Os dados enviados por sigqueue devem estar na forma de consórcio

#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include<iostream>
#include <signal.h>
#include<stdio.h>
#include <stdlib.h>
using namespace std;

//带参数的信号
void sigaction_func(int num, siginfo_t* info, void* vo);
int main(){
    int pid = 0;
	//准备结构体
	struct sigaction  act;
	act.sa_sigaction = sigaction_func;
	act.sa_flags = SA_SIGINFO;//带参数的信号
	//绑定信号
	sigaction(SIGUSR1,&act,NULL);  //发送是sigqueue
	
	pid = fork();

	if (pid == 0)
	{
		while (true)
		{
			cout << "子进程运行中 ...pid =" << getpid() << endl;
			sleep(1);
		}
	}
	else if (pid > 0)
	{
		sleep(2);
		//准备要传递的数据
		union sigval value;
		value.sival_int = 111;
		//带参数发送信号
		sigqueue(pid, SIGUSR1, value);//第三个参数跟之前不一样,是一个联合体
		//卡住父进程
		while (1) {}
	}

	return 0;
}

void sigaction_func(int num, siginfo_t* info, void* vo)
{
	int x = info->si_int;
	cout <<"当前进程pid = "<<getpid()<<"  sigaction_func函数被调用了,num =  " << num << "  信号传递过来的数据是 x =  " << x<< endl;
}

2. Resultados em execução

4. Resumo

Os dados passados ​​no exemplo anterior são apenas um inteiro, então algumas pessoas podem notar o segundo parâmetro void * na união sigval (como mostrado abaixo), pensando que ele pode ser usado para implementar outros tipos de dados, mas este não é o caso.

1. Quando os primeiros desenvolvedores desenvolveram os sinais, eles só suportavam a transferência de dados do tipo int, então eles pensaram em reservar um void * para uso posterior, mas infelizmente, a transferência de dados de void * ainda não é suportada na versão ubuntu20, e isso ainda não foi realizado.Atualização, então dados complexos (arrays, estruturas) não podem ser passados, o que é muito insípido.

2. Como o IPC possui cinco métodos de comunicação, não é apenas possível usar sinais para transferir dados entre processos, porque a operação problemática dos sinais torna apenas o uso básico da comunicação

3. Quando o processo filho recebe um sinal desconhecido (por exemplo, altere SIGUSR1 no código acima para SIGUSR2 em sigqueue(pid, SIGUSR1, value);) e a função de ligação não é executada, o resultado em execução é o seguinte, o processo filho não sabe Faça nada e você ficará preso

Compile novamente no linux

Neste ponto, verifique se o estado do processo é Z+ (estado zumbi - o processo filho termina antes do processo pai. Há um loop infinito no processo filho, que não deve terminar primeiro, mas porque o processo filho recebe um sinal desconhecido, será interrompido, o processo filho está preso lá, ou seja, a coisa original não faz e não sabe o que fazer a seguir, entra no estado zumbi, ocupa recursos e deve ser evitado)

4. Quando tenho apenas um processo, use kill para enviar um sinal para ele no linux

 O processo recebe um sinal desconhecido (sinal nº 10), imprime o sinal definido pelo usuário 1, verifica o status do processo e descobre que o pid não pode ser encontrado, ou seja, é interrompido e destruído, como se tivesse jogado o função de matar o processo (o processo pai anterior envia um sinal desconhecido para o processo filho, mas ele fica travado). Então, para garantir a execução normal do processo, você precisa usar blindagem de sinal
 

Picadora de pequeno porte

 

Indique a fonte ao carregar

Desenvolvimento multiplataforma (Linux) baseado em VS2019 C++ (1.4.2) - com sinais de parâmetro

A máscara de sinal de aprendizagem é a seguinte

https://blog.csdn.net/hml111666/article/details/123683046

Acho que você gosta

Origin blog.csdn.net/hml111666/article/details/123564522
Recomendado
Clasificación