プロセス間通信とUnixドメインソケット

最近、私はかなり興味深い問題を解決しなければなりませんでした。

アプリケーション、つまりマルチキャストストリームをファイルに書き込むデーモンを作成する必要がありました。

この場合、複数のマルチキャストストリームを並行して記述する必要がありました...

さらに...これらの悪魔を一元管理する必要があります!



理論のビット


実際、アプリケーション自体は非常に単純です...しかし、管理の問題が発生します...デーモンが既に実行されている場合、コマンドを転送する必要があります...たとえば、ストリームが書き込まれるファイルを変更するか、記録を完全に停止します。 質問が発生しました-そのような悪魔を管理する方法...



いくつかのGoogleページを押し出し、難解な記事を読んだ後、Unixドメインソケットの亜種にこだわることになりました...



アーキテクチャは単純です...起動時に、「why write」パラメータに加えて、その一意のIDが渡され、それによって制御ソケットの名前が生成されます(corny sock_ [id])。 すべてのソケットは、サーバー上の所定のディレクトリに作成されます... / tmp / my_socks /とします。

したがって、起動時のマネージャーアプリケーションは、このディレクトリのリストを作成し、開始したプロセスを確認します...その後、これらのプロセスに(同じソケットを介して)pingを実行し、実際に生きているものを確認します...デッドソケット(どのプロセス理由もなく)-あなたはすぐにそれを削除することができます...



さて、ソケットが開いた後、特定のプロセスとコマンドを交換することができます...このような双方向のプロセス間通信が判明します。



しかし、これは理論です! 以下はいくつかの練習です...



実装


ストリーム記録アプリケーションがgccに実装されました

必要な包含物と構造



#include <sys/types.h><br/> #include <sys/socket.h><br/> #include <sys/un.h><br/> #include <netdb.h><br/> #include <arpa/inet.h><br/> #include <unistd.h><br/> #include <netinet/ in .h><br/> #include <stdlib.h><br/> #include <stdio.h><br/> #include < string .h><br/> #include <fcntl.h><br/> <br/> int ctrlsock, ns;<br/> struct sockaddr_un saun;<br/> <br/>







ソケットを初期化して、リッスンを開始します。



void init_ctrl_socket() {<br/> // .. AF_UNIX unix-socket <br/> if ( ( ctrlsock = socket(AF_UNIX, SOCK_STREAM, 0 ) ) < 0 ) {<br/> savelog( "ERROR: control socket creating error" );<br/> exit( 1 );<br/> }<br/> <br/> // .. .. <br/> int flags = fcntl(ctrlsock, F_GETFL, 0 );<br/> if ( fcntl(ctrlsock, F_SETFL, flags | O_NONBLOCK) < 0 ) {<br/> savelog( "ERROR: don't set socket on nonblocket mode" );<br/> exit( 1 );<br/> }<br/> <br/> // .. <br/> // . - .. <br/> <br/> saun.sun_family = AF_UNIX;<br/> strcpy(saun.sun_path, "/tmp/my_socks/sock_01" ); // <br/> int len = sizeof (saun.sun_family) + strlen(saun.sun_path);<br/> <br/> if (bind(ctrlsock, ( struct sockaddr *)&saun, len) < 0 ) {<br/> savelog( "ERROR: control socket binding error" );<br/> exit( 1 );<br/> }<br/> <br/> if (listen(ctrlsock, 5 ) < 0 ) {<br/> savelog( "ERROR: control socket listening error" );<br/> exit( 1 );<br/> }<br/>}<br/> <br/> <br/>







ソケットからコマンドを受け取る:



void check_ext_command() {<br/> int fromlen = sizeof ( struct sockaddr );<br/> if ( (ns = accept(ctrlsock, ( struct sockaddr *) &fsaun, &fromlen) ) > 0 ) {<br/> char lbuf[ 255 ];<br/> int ilen;<br/> ilen = recv( ns, &lbuf, 255 , 0 );<br/> lbuf[ilen]= '\0' ;<br/> do_remote_command( lbuf ); // .. <br/> close(ns);<br/> } <br/>}<br/> <br/>







ソケットへの書き込みは通常どおり行われます。



char msg = "my message" ;<br/>send( ns, msg, strlen(msg), 0 );<br/> <br/>







プロセスマネージャー


プロセスのマネージャーはphpで作成されました。 ブラウザを介してそれらを管理するのを便利にするために...

既存のプロセスをポーリングする例を次に示します



class reccontrol {<br/> <br/> var $socket_path = '/tmp/my_socks/' ; // <br/> var $socket_prefix = 'sock_' ; // ( :)) <br/> var $list = array ();<br/> <br/> function getList() {<br/> $this ->writers_info = array ();<br/> $arr = scandir( $this ->socket_path);<br/> unset ( $arr [ 0 ]); // . <br/> unset ( $arr [ 1 ]); // .. <br/> foreach ( $arr as $k => $s_name ) {<br/> if ( ! $this ->ping( $s_name ) ) { <br/> // - <br/> @unlink( $this ->socket_path . $s_name ); <br/> unset ( $arr [ $k ] ); <br/> }<br/> }<br/> $this -> list = $arr ;<br/> <br/> }<br/> <br/> // " " <br/> function ping( $s_name ) {<br/> $socket_name = $this ->socket_path. $s_name ; // <br/> $sock = $this ->getSock( $socket_name ); // <br/> <br/> if ( ! $sock ) return false ; // - <br/> <br/> $buf = "ping" ;<br/> if ( @socket_send( $sock , $buf , strlen( $buf ), 0 ) == false ) {<br/> return false ; // - <br/> }<br/> <br/> $buf = '' ;<br/> @socket_recv( $sock , $buf , 1024 , 0 );<br/> if ( $buf ) { <br/> // $buf - , .. - <br/> addlog( " " . $s_name . " : " . $buf ); <br/> }<br/> <br/> socket_close( $sock ); <br/> return true ; // - ! <br/> }<br/> <br/> // unix .. , :) <br/> function getSock( $socket_name ) {<br/> // , AF_UNIX <br/> $socket = @socket_create(AF_UNIX, SOCK_STREAM, 0 ); <br/> // $socket_name - /tmp/my_socks/sock_1 - .. <br/> if ( @socket_connect( $socket , $socket_name ) == false ) { <br/> <br/> $err = socket_last_error();<br/> if ( $err ) {<br/> return false ; // :( <br/> }<br/> } else {<br/> return $socket ; // - <br/> }<br/> }<br/> <br/>} <br/>







ここにそのような相互作用があります...

基本的な機能を実行する小さなコードのみがここに公開されています...全体として、それは非常に面倒に見え、特定のプログラムは平均的な素人には役に立たない...全体のポイントは制御のアイデアにあります...

Webページにアクセスして、いくつかのプロセスから情報を取得し(pingで返される)、特定のプロセスに特定のコマンドを与えることができます...



All Articles