Libapap kullanılarak pcap verileri toplanarak pcap_dump işlevi kullanılarak stdout kullanarak, FILE * olarak stdout ile programlanan bir programım var. SIGINT üzerinde biraz temizlik gerekiyor, bu yüzden sigaction() ile başa çıkıyorum. Bu bir kabuktan yürütüldüğünde güzel çalışır. Bununla birlikte, bu programın işe yaramadığı görülen başka bir program tarafından çağrılması amaçlanmıştır. Bu "arayan" program bir boru(), sonra bir fork() çağırır, daha sonra çocuğun stdout dosya tanımlayıcısı kapanır ve borunun yazma ucuyla değiştirilir. Son olarak, daha önce bahsedilen pcap programı çocuk işleminde yürütülür. Bu sayede pcap verileri, arayan programa boru yoluyla yazılır. Bu da güzel çalışıyor. Ancak, boruya yazarken çocuk sürecine bir SIGINT yolladığımda (iyi, pcap programı yazımını stdout olarak düşünür, fakat dosya tanıtıcı değiştirildi), sinyal düşüyor ve sinyal işleyici işlevi asla hiç çağırılmaz.SIGINT sinyali bir boruya yazılırken düşüyor
Neden? Eğer pcap verilerini stderr veya bir dosyaya yazarsam, SIGINT asla düşmez. Sadece boruya yazarken. Biz boru/çatal kuruyorlar nasıl İşte
olduğunu/yürütün: çocukta
kill(pid, SIGINT);
, bizim pcap_loop için geri arama işlevi:
int fd[2];
//Create pipe
pipe(fd);
pid = fork(); //We forked a child
if(pid == 0){ //We are the child now
close(1); //close child's stdout
dup(fd[1]); //duplicate child's stdout to the write end of the pipe
close(fd[0]); //close unused file descriptors
close(fd[1]);
//Load the new program
execlp("./collectraw", "collectraw", NULL);
perror("Exec");
exit(127); //Should never get called but we leave it so the child
//doesnt accidently keep executing
}
else{ //We are the parent
//Set up the file descriptors
close(fd[1]);
}
sonra kullandığımız çocuğu öldürmek() kadar basit olabilir:
void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet){
write(1,"<pretend this is like a thousand zeros>",1000); //write to stdout, which is really a pipe
}
Ve temelde her zaman SIGINT düşecek. Bu arada çekilecek birçok paket var, bu yüzden neredeyse her zaman geri arama işlevinde olduğunu varsaymak oldukça güvenli.
biz
write(1,...); //write to stdout, which is really a pipe
den
write(2,...); //write to stderr, or writing to a file would work too
geçtiğinizdeyse Ama sonra her şey yine kıyak olur.
SIGINT'imiz bir yazı yazılırken neden boruya düşüyor?
Yardımlarınız için teşekkürler.
DÜZENLEME: Çocuğun SIGINT işleyicisine hiç çağrılmadı, ama neden çocukta gerçekten bir sorun değildi, ebeveynte bir problemdi. Ben gibi çocuğu öldürmek için kullanılan:
if(kill(pid, SIGINT) == -1){
perror("Could not kill child");
}
close(pipefd);
fprintf(stdout, "Successfully killed child\n");
Ve bu bizim SIGCHLD işleyici olarak kullanılan: hemen boruyu kapatarak kabul edilen yanıt açıklandığı gibi
void handlesigchild(int sig) {
wait();
printf("Cleaned up a child\n");
}
Yani, çıkmak için çocuğumuzu neden oldu SIGINT'in ele alınmasından önce bir SIGPIPE ile. Yakın zamanda (pipefd) SIGCHLD işleyicisine taşındık ve şimdi çalışıyor.
Yığın Taşması'na Hoş Geldiniz. Lütfen yakında [Hakkında] sayfasını okuyun. Genel olarak, C ya da C++ dil etiketi olarak seçmelisiniz ve her ikisini de değil - çünkü C++ için uygun olan çözümler genellikle C için uygun değildir ve tersi de çoğu zaman geçerlidir. –
"Strace" altında işlemler nasıl çalışıyor? (Linux'un işletim sisteminiz olduğunu varsayarsak) Ayrıca, sinyal işleme kodunuzu gönderin. –
Bunun nedeni, sinyal tutucunuzun (varsayacağınız varsayılarak) boruyu kapatmıyor olması (şu anda kullanımda olan)? Belki de denemeye değer. – Addison