【问题标题】:sigusr1 between parent and child in cc中父母和孩子之间的sigusr1
【发布时间】:2018-02-26 01:28:58
【问题描述】:

我想实现一个 UDP 服务器,它与三个线程(通过三个端口)一起工作,做同样的事情。在一个线程中,每个线程都有一个父节点和一个子节点:父节点等待来自客户端的请求,子节点增加一个变量。当父母收到请求时,它会向孩子的pid发送一个信号(SIGUSR1)(尝试,我使用parentpid+1)。 child 默认情况下增加变量,通过 SIGUSR1 写一些东西(例如:“我在 sigurs1”),但实际上我还想将变量的状态发送到主线程。然而,这是代码:

/**
@defgroup Group4 UDP Client and Server

@brief UDP/IPv4 Client and Server
@{
*/
/**
@file 	UDPServer.c
@author Catiuscia Melle

@brief 	Presentazione di un UDP Echo Server IPv4.

Il server, in un ciclo infinito:
- riceve un messaggio 
- lo re-invia in echo.
*/


#include "Header.h"

//@@@ PRIMA DI TUTTO INCLUDIAMO LA LIBRERIA PER I SEGNALI
#include <signal.h>


void *thread_function(void *arg);
int stock = 0;

//@@@ Il sigset_t viene utilizzato per rappresentare un signal set
sigset_t	mask;

int main(){
	
	printf("\tIPv4 UDP Server app\n");
	
	int port1 = PORT, port2 = PORT2, port3 = PORT3;
	
	//INITIALITE THREAD AND VARIABLES FOR THREAD
	int thres; //response of the thread
    pthread_t a_thread, a_thread2, a_thread3;
    void *thread_result;
    
    //CREATE THREAD 1
    thres = pthread_create(&a_thread, NULL, thread_function, &port1);
    if (thres != 0) {
        perror("Thread creation failed");
        exit(EXIT_FAILURE);
    }
    
    //CREATE THREAD 2
    thres = pthread_create(&a_thread2, NULL, thread_function, &port2);
    if (thres != 0) {
        perror("Thread creation failed");
        exit(EXIT_FAILURE);
    }
		
	//CREATE THREAD 3
    thres = pthread_create(&a_thread3, NULL, thread_function, &port3);
    if (thres != 0) {
        perror("Thread creation failed");
        exit(EXIT_FAILURE);
    }
	
	thres = pthread_join(a_thread, &thread_result);
  	if (thres != 0) {
    	perror("Thread join failed");
    	exit(EXIT_FAILURE);
    }
    
    thres = pthread_join(a_thread2, &thread_result);
  	if (thres != 0) {
    	perror("Thread join failed");
    	exit(EXIT_FAILURE);
    }
        			
    thres = pthread_join(a_thread3, &thread_result);
  	if (thres != 0) {
    	perror("Thread join failed");
    	exit(EXIT_FAILURE);
    }
		
	
	
return 0;
}

void *thread_function(void *arg) {

	pid_t	pid;
	int parentpid = getpid();
	
	printf("Il pid della thread vale %d\n",parentpid);
	
	int port = *((int *) arg);
	
//@@@ Nella variabile signo salverò il numero di segnale che mi restituisce la wait
	int err, signo;
	
	printf("Porta %d\n",port);
	

	printf("ENTER TO THREAD\n");
	

	int res = 0; //valore di ritorno delle APIs

	/*
	socket: servirà per la comunicazione col server
	*/
	int sockfd = 0;
	
	/*
	open socket di tipo datagram
	*/
	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if (sockfd == -1)
	{
		perror("socket error: ");
		return FAILURE;
	}
	
	/*
	indirizzo IPv4 del server, senza hostname resolution
	*/
	struct sockaddr_in server;
	socklen_t len = sizeof(server);
	
	memset(&server, 0, sizeof(server)); //azzero la struttura dati
	server.sin_family = AF_INET; //specifico l'Address Family IPv4
	
	/*
	Specifico l'indirizzo del server: qualsiasi interfaccia
	*/
	server.sin_addr.s_addr = htonl(INADDR_ANY);
		
	/*
	Specifico la well-known port
	*/
	server.sin_port = htons(port);
	
	//setto l'indirizzo well-known del socket
	res = bind(sockfd, (struct sockaddr *)&server, len);
	if (res == -1)
	{
		perror("Bind error: ");
		close(sockfd);
		exit(1);
	}//fi
	
		
	ssize_t n = 0;
	char buffer[BUFSIZE];
	
	struct sockaddr_in client;
	char address[INET_ADDRSTRLEN] = "";
	
	int quit = 0;
	
	if ((pid = fork()) < 0) {
		printf("Fork error<n");
	} else if (pid == 0) {		/* child */
		printf("child dal pid %d\n",getpid());
		
		while(1){
			
			
			
			        //@@@ La sigwait non fa che attendere l'arrivo di un segnale
        	err = sigwait(&mask, &signo);
	
		
			//@@@ Una volta terminata la sigwait, ossia quando ha ricevuto un segnale
			//(se no è successo un errore), possiamo switchare il segnale arrivato, che
			//è salvato in signo
			switch (signo) {
		
			//@@@ Ora gestisco, se gli ho mandato un SIGUSR1, ossia un flag che, arrivato 
			//a destinazione indica di eseguire quel segnale che il processo che lo riceve
			//lo implementa come vuole. Si sa che si deve eseguire quel segnale, di libera
			//interpretazione
			case SIGUSR1:
				printf("Sigusr1\n");
				printf("Stock vale %d\n",stock);
				break;
        
     	   //@@@ In caso gli mandassi SIGINT, valuta sempre se ci sono errori e poi esci
    	    case SIGINT:
   	    		printf("Sigint\n");
			//@@@ Di default comunque, controlla se ci sono errori e poi esci
			default:
				stock++;
				printf("Sto producendo %d dalla porta %d\n",stock, port);
				sleep(2);
			}
			
			
			
			
			
			
		}
	} else {
		printf("parent dal pid %d\n",getpid());				/* parent */
		
		while (!quit)
	{
		printf("Main thread entrato nel ciclo\n");
		n = recvfrom(sockfd, buffer, BUFSIZE-1, 0, (struct sockaddr *)&client, &len);
		
		printf("Mando segnali");
		 //@@@ Inizializza il segnale settato set a escludere tutti i segnali definiti
    	sigemptyset(&mask);
    	//@@@ Aggiunge il segnale signum al segnale settato set. Con sigaddset modifichiamo
    	//set, ma non blocchiamo o sblocchiamo alcun segnale!
    	//Mettiamoli quindi SIGURS1
		sigaddset(&mask, SIGUSR1);
		//@@@ E anche SIGINT
		sigaddset(&mask, SIGINT);
		//@@@ pthread_sigmask esamina e cambia segnali bloccati. Con SIG_BLOCK il set
		//risultante è l'unione del set corrente e il set di segnale indicato da set
		if ((err = pthread_sigmask(SIG_BLOCK, &mask, NULL)) != 0)
		{
        	fprintf(stderr, "thread mask failed\n");
    		exit(EXIT_FAILURE);
    	}
    	
    	kill(parentpid+1,SIGUSR1);
    	
    	printf("Segnale inviato al pid %d\n",(parentpid+1));
		
		if (n == -1)
		{
			perror("recvfrom() error: ");
			continue;
// 			close(sockfd);
// 			return FAILURE;
		}

	
	}//wend
		
	printf("Stockmann %d\n",stock);
	
	//qui non ci arrivo mai...	
	close(sockfd);
	
	}

	
	
		
			  
			
return NULL;	
}


/** @} */

这是Header.h(但没必要看)

/**
@addtogroup Group11
@{
*/
/**
@file 	Header.h
@author Catiuscia Melle

@brief 	Header comune al client e server dell'esempio

L'header definisce costanti comuni al client e server.
*/

#ifndef __HEADER_H__
#define __HEADER_H__

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h> //resolver related functions

#include <sys/types.h> //necessario su Mac
#include <stdlib.h>

#include <ctype.h> //toupper()
#include <stdbool.h>

//THIS FOR RAND FUNCTION
#include <stdlib.h>
#include <time.h>

//THIS FOR THREADS
#include <pthread.h>

#define PORTNUMBER 		49152 		/**< UDP listening port, decimal */
#define PORT 		49152 		/**< UDP listening port, decimal */

#define PORT2 		49153 		/**< UDP listening port, decimal */
#define PORT3 		49154 		/**< UDP listening port, decimal */

#define SERVICEPORT 	"49152" 	/**< UDP listening port, name */
#define PORT_STRLEN 6 /**< lunghezza di una stringa rappresentativa di un indirizzo di trasporto */

#define BACKLOG 10 	/**< dimensione della coda di connessioni */

#define SIZE 15 /**< dimensione della coda di connessioni concorrenti gestite dal server */

#define BUFSIZE 512 /**< dimensione del buffer di messaggio */

#define FAILURE 3 	/**< definizione del valore di errore di ritorno del processo in caso di errori delle Sockets API */

#define INVALID 5 	/**< se i due processi non sono avviati col giusto numero di parametri */

#define ERROR 1 /**<  valore di errore */

#define INSUCCESS -1 /**< valore di ritorno non valido */

#define SEMAPHORE_NAME "gbrunetta317"

#endif /* __HEADER_H__ */

/** @} */

问题是当我用客户端发送一些东西时, case: Sigurs1 里面的值没有出现:

实际上,它不会从 child 中定义的 SIGUSR1 中返回任何内容,但是您可以看到它停止了该进程(实际上您可以看到它不再使用端口 49512,因为 pidparent+1 关联与那个端口)。我希望我很清楚。我该如何解决?

【问题讨论】:

  • kill(parentpid+1,SIGUSR1); 先拍,再问问题。
  • 你为什么不直接用kill(pid, ...给孩子发信号呢?
  • pid?因为父 pid 与子 pid 不同..
  • 有parentpid和child的另一个prid进入三个线程分别是parentpid+1,parentpid+2,parentpid+3,从终端可以看到
  • 但也许你是对的!因为 pid 是孩子的 pid...对吗?

标签: c multithreading udp signals fork


【解决方案1】:

我发现 shmat 失败了。我不知道为什么,但我根据这个例子重写了代码:How to trigger SIGUSR1 and SIGUSR2? 现在它工作正常。

【讨论】:

    猜你喜欢
    • 2015-01-18
    • 2017-08-26
    • 2011-02-20
    • 1970-01-01
    • 2015-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-21
    相关资源
    最近更新 更多