LINUX IPC

0

Witam.

Mam problem .
Mam napisać klienta do pewnego serwera czasu. Narpiew uruchamiam serwerczasu, biore id serwera,
wpisuje do pliku i uruchamiam. Niestety wysłany sygnał nie dochodzi do serwera.
może ktoś pomoze

serverczas.c

 
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#include<fcntl.h>
#include<sys/shm.h>
#include<sys/wait.h>
#include<sys/ioctl.h>
#include "server.h"
#include<signal.h>

#define klucz 8001
#define prawa 0660


struct czas {
int sid,cid;     // identyfikatory procesu  servera i klienta 
char t[40];      // pole do przechowania czasu
};

/* funkcje bliblioteczne

    (1) bcopy(source,dest,ilosc_bajtow) - kopiuje bajty
    (2) bzero(p,ilosc bajtow) - zeruje blok bajtow wskazywany przez p  
*/

  
int shmid,id;
void *pw=0;
struct czas cz;

void zapis() {  // wykonuje zapis czasu do bloku pamieci wspolnej

//Moje dodanie
printf("Otzymalem od klienta zapytanie i wpisuje czas do wspolnego bufora");

time_t czas=time(0);
bcopy(pw,&cz,sizeof(cz));  // kopiuje do struktury zawartosc bloku pw
			  // teraz struktura cz ma wypelnione pola sid i cid
                          
strcpy(cz.t,ctime(&czas)); // kopiuje czas do struktury cz
bcopy(&cz,pw,sizeof(cz));  // kopiuje strukture cz do pw
}


void zakoncz(){       // po otrzymaniu sygnalu odlacza pamiec wspolna
shmdt(pw);
}




main(int arg, char **argv)
{
int pid=-1;
int ch=getpid(),s,fd;

 signal(SIGCLD,SIG_IGN); //proces macierzysty nie musi czekac na zakonczenie
//                         procesu potomnego
//                         zapobiega tworzeniu procesow zombie 

// oznaczenia:
// S - oczekiwanie nie aktywne (drzemie)
// T - proces zawieszony
// Z - proces zombie
// R - proces aktywny


if ( arg < 2) {
 puts("server start|stop"); exit(0);
return 0;}

if (strcmp(argv[1],"stop")!=0 && (strcmp(argv[1],"start")!=0 )){
   puts("server start|stop"); exit(0);} 



if (strcmp(argv[1],"stop")==0 ) {     // zatrzymywanie  servera
              stanserwera(0);
              exit(0);
}




signal(SIGUSR1,zapis);
signal(SIGTERM,zakoncz);

if ((ch=fork())== -1) perror("can't fork"); //tworzy proces potomny
 
if (ch==0) {
pid=getpid();
if (strcmp(argv[1],"start")==0 ) {      // uruchamia server jako demon

stanserwera(1);                        // wpisuje do p.w swoj numer procesu


//moja modyfikacja
puts("server startuje i jego pid to %d", getpid());   
}


setpgrp();  // zmienia grupe procesow


if((fd=open("/dev/tty",O_RDWR))>=0)    // odlacza terminal sterujacy       
{
ioctl(fd,TIOCNOTTY,0);
close(fd);
}



// zamyka deskryptory plikow
//close(0);
//close(1);


// dzialanie servera



// tworzy segment pamieci wspolnej
if ( (shmid=shmget(klucz,40*sizeof(char),IPC_CREAT|prawa)) < 0) 
    perror("blad servera");

// udostepnia segment pw.
if ( (pw=shmat(shmid,0,0)) == (char*)-1) 
  perror("server start stop");

bzero(&cz,sizeof(cz));
cz.sid=getpid();
bcopy(&cz,pw,sizeof(cz));


while (1) {
     pause();  // po nadejsciu sygnalu SIGUSR1 budzi sie i wykonuje funkcje zapis
     kill(cz.cid,SIGUSR1); // wysyla sygnal do klienta ze blok pw zawiera czas
     }
    
}

else{ }
 

return 0;
}

klientczas.c

 
/* funkcja fork tworzy kopie procesu wywolujacego ta funkcje */



#include <stdlib.h>
#include<stdio.h>
#include<strings.h>
#include<time.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/wait.h>
#include<sys/ioctl.h>
#include<signal.h>

#define klucz 8001
#define prawa 0660

struct czas {
int sid,cid;     // identyfikatory procesu  servera i klienta 
char t[40];      // pole do przechowania czasu
};


char *buf;
int shmid;
void *pw;
int pidServera = 3490;



/******************* zadanie *************************
 Napisac program klienta dla serwera "serwer_czas.c"
 ktory bedzie wysylal do serwera polecenie podania czasu
 a nstepnie wypisze odczytany czas na ekranie. Klient i serwer
 komunikuja sie poprzez blok pamieci wspolnej
 czynnosci klienta:
 1) tworzy blok pamieci wspolnej ktory przechowuje strukture czas
 2) odczytuje z niego numer serwera
 3) wpisuje swoj numer procesu do bloku p.w
 4) wysyla sygnal SIGUSR1 do serwera
 
*****************************************************/ 




main(int arg, char **argv)
{
  struct czas cz;
  cz.sid = getpid();
  // dostep do wspolnej pamieci
  void *pw;
  if ( (shmid=shmget(klucz,size,prawa|IPC_CREAT)) < 0) perror("blad: tworzenie segmentu"); 
  if ( (pw=shmat(shmid,0,0)) == (char*)-1) perror("Nie udestepniono segmentu udostepnianie segmentu"); 
  
  kill(3490, SIGUSR1);
  sleep(1);

return 0;
}

0

kill(3490, SIGUSR1); - wydaje mi się to absurdalnym wywołaniem. Skąd taka pewność, że za każdym razem PID serwera to 3490 ? Prawdopodobieństwo uzyskania przez proces tego samego numeru jest znikome ;)

0

Sam zmieniam wartosc pid

0

Sam zmieniasz ale po co ? PID należy pobrać, bo jak widzę struktura czas wyposażona jest w takie pola jak sid i cid. Kopiowanie struktury z/do pamięci współdzielonej za każdym razem to jakiś żart. Można to zrobić bardziej elegancko:

/* fragment kodu z klientczas.c */
cz = (struct czas *)pw;
cz->cid = getpid(); /* bezpośredni zapis do shm! Gdzie się podziało kopiowanie ?! ;) */
printf("Odebrano pid server: %d\n", cz->sid); /* bezpośredni odczyt z shm */
kill(cz->sid, SIGUSR1);

Idąc dalej pid przechowuje się w typie pid_t nie int. Innym problemem w twoim kodzie jest to, że serwer nie pokaże komunikatów aż nie "przepchamy" strumienia wyjścia funkcją fflush(). Innym roziwiązaniem jest dodawanie znaku nowego wiersza w wywołaniach printf, co automatycznie opróżnia bufor wyjściowy(użyłem tego w kodzie wyżej). Warto pomyśleć o jakieś estetyce kodu, bo takiej tu nie widzę. Pozbądź się kopiowania shm to większość problemów zostanie zlikwidowanych.

pozdrawiam.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.