2016-07-19 4 views
0

私はPerlスレッドでシリアルポートを使用しています。私はスレッドで読み書きできます。しかし、別のアプリケーションがポートを使用して後で再び開くことができるようにシリアルポートを閉じたい場合、私はもう読み書きできません。どうやってするか?Linux PerlスレッドSerialPortを閉じてもう一度開きます

my $dev; 
my $port = "/dev/ttyACM0"; 
my $run :shared = 0; 
my $thr; 
my $read_thr; 

sub port_init 
{ 
    $dev = Device::SerialPort->new($port, 1) || die "Cannot open $port: $!\n"; 

    $dev->baudrate(115200); 
    ... 

    $run = 1; 
} 

sub read_port # read async 
{ 
    my $str; 
    while ($run == 1) 
    { 
     $str = $dev->lookfor; 
     if ($str ne "") 
     { 
      print "recv: $str\n"; 
     } 
     sleep 0.5; 
    } 
} 

sub write_port 
{ 
    my $msg = shift; 
    if ($run == 1) 
    { 
     $dev->write($msg."\r"); 
    } 
} 

sub close_port 
{ 
    $run = 0; 
    $dev->close; 
} 

# Main 
port_init(); 
$read_thr = threads->new(\&read_port); 
$read_thr->detach(); 

if ("event1 occurs") # send cmd to port 
{ 
    $thr = threads->new(\&write_port, "ATI"); # works, response received 
    $thr->detach(); 
} 

if ("event2 occurs") # another application is requesting the port 
{ 
    $thr = threads->new(\&close_port); 
    $thr->detach(); 

    # wait till application has finished 

    port_init(); 

    $read_thr = threads->new(\&read_port); 
    $read_thr->detach(); 

    # send cmd to port, doesn't work 
    $thr = threads->new(\&write_port, "ATI"); 
    $thr->detach(); 

} 

ポートを閉じた後、もう使用できません。 read_portは、Device :: SerialPort :: inputのエラー#9を2回目に起動した後にスローします。パーサーは常にアクセス可能でなければならないので、スレッドが必要です。

答えて

0

あなたの実際のコードを投稿しなくても、言うことは難しいです。そしてport_init()でそれをインスタンス化 - - しかし、彼らは起動時に、各スレッドは、このオブジェクトのクローンを継承し、私はあなたがスレッドを開始する前に$devを作成するために問題はなると思うしかし

これは非常に乱雑な状態に陥ります。私は強くお勧めします。は、まずに入っています。各スレッドはまだ実行中です(アクティブではあるがデタッチされている)ので、ポートファイルハンドルのインスタンスを保持しています。

これは非常に乱雑ですが、これが正しく動作しない理由はほとんどありません。

私はあなたが最初にこのような状況に陥ることはお勧めしません - そのようなポートを共有しないで、すべてのものを扱うスレッドを1つだけ持ってください。 IPCの共有変数より複雑なものが必要な場合は、Thread::Queueを使用してください。

関連する問題