現在、Raspberry Pi 3(Linux Ubuntu)上で実行されているCプログラムで、組み込みシステムでネットワーキングを設定するためのWebページインターフェイスを提供しています。USBシリアルポートのプログラミングに「悲惨な結果」があります
コードは、Code :: BlocksをGDBデバッガで使用して開発されています。私はウェブサーバーにmicrohttpdを使用していますが、それに加えてさまざまなWebページもすばらしく働いています。私は現在、「シリアルプログラミングガイドfor POSIXオペレーティングシステム」の情報を使用して、組み込みシステムへのUSBシリアルリンクを作成中です。
以下のコードは、ターゲットシステムへのUSBシリアルリンクを開く責任があり、正常に動作するようです。私がプログラムを閉じて、それを再起動すると(コマンドラインやCode :: Blocksのスタンドアローンのいずれかで)、microhttpdが2度目に閉じられます。ブラウザウィンドウはもう接続されません。さらに、Code :: Blocks内からデバッガもホースされています。プログラムが起動されると、デバッガは一時停止または停止できません。唯一の方法は、プロジェクトを閉じることによってそれを終了させることです。
問題は明らかに関数内にあります。私はその呼び出しをコメントすることができ、以前と同じようにすべて機能します。残念ながら、問題が発生したら、唯一の解決策はPiを再起動することです。
私はスクリプト言語(Tcl)を使用する前にこのようなことをしましたが、今回はPiが高帯域幅データロギングプログラムを実行しているため、非解釈言語からパフォーマンスを向上させたいと考えています。同様のUSBシリアルインターフェイスを介して。
コードを以下に示します。
/******************************************************************************/
/* This function scans through the list of USB Serial ports and tries to */
/* establish communication with the target system. */
/******************************************************************************/
void tapCommInit(void) {
char line[128];
char port[15]; // this is always of the form "/dev/TTYACMn"
char *ptr;
FILE *ifd;
struct termios options;
uint8_t msgOut[3], msgIn[4];
msgOut[0] = REQ_ID; // now prepare the message to send
msgOut[1] = 0; // no data so length is zero
msgOut[2] = 0;
/**************************************************************************/
/* First, get the list of USB Serial ports. */
/**************************************************************************/
system("ls -l /dev/serial/by-path > usbSerial\n"); // get current port list
ifd = fopen("usbSerial", "r");
logIt(fprintf(lfd, "serial ports: \n"));
/**************************************************************************/
/* The main loop iterates through the file looking for lines containing */
/* "tty" which should be a valid USB Serial port. The port is configured */
/* in raw mode as 8N1 and an ID request command is sent, which has no */
/* data. If a response is received it's checked to see if the returned */
/* ID is a match. If not, the port is closed and we keep looking. If a */
/* match is found, tapState is set to "UP" and the function returns. If */
/* no match is found, tapState is left in the initial "DOWN" state. */
/**************************************************************************/
while(1) {
if (fgets(line, 127, ifd) == NULL) { // end of file?
break; // yes - break out and return
}
ptr = strstr(line, "tty"); // make sure the line contains a valid entry
if (ptr == NULL) {
continue; // nothing to process on this line
}
strcpy(port, "/dev/"); // create a correct pathname
strcat(port, ptr); // append the "ttyACMn" part of the line
port[strlen(port)-1] = 0; // the last character is a newline - remove it
logIt(fprintf(lfd," %s\n", port)); // we have a port to process now
cfd = open(port, O_RDWR | O_NOCTTY | O_NDELAY); // cfd is a global int
if (cfd == -1) {
logIt(fprintf(lfd, "Could not open port: %s\n", port));
continue; // keep going with the next one (if any)
}
fcntl(cfd, F_SETFL, 0); // blocking mode
tcgetattr(cfd, &options); // get the current port settings
options.c_cflag |= (CLOCAL | CREAD); // ena receiver, ignore modem lines
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // raw, no echo
options.c_oflag &= ~OPOST; // no special output processing
options.c_cc[VMIN] = 0; // minimum number of raw read characters
options.c_cc[VTIME] = 10; // timeout in deciseconds (1 second timeout)
tcsetattr(cfd, TCSANOW, &options); // set options right now
cfsetispeed(&options, B115200); // input baud rate
cfsetospeed(&options, B115200); // output baud rate
options.c_cflag &= ~(CSIZE | PARENB | // clear size bits, no parity
CSTOPB | CRTSCTS); // 1 stop bit, no hw flow control
options.c_cflag |= CS8; // now set size: 8-bit characters
options.c_cflag &= ~(IXON | IXOFF | IXANY); // no sw flow control
if (write(cfd, msgOut, 3) < 3) {
logIt(fprintf(lfd, "Sending of output message failed\n"));
close(cfd);
continue;
}
if (read(cfd, msgIn, 4) != 4) {
logIt(fprintf(lfd, "Didn't get expected amount of return data\n"));
close(cfd);
continue;
}
if (msgIn[3] != HOST_ID) {
logIt(fprintf(lfd, "Got the wrong HOST_ID response\n"));
close(cfd);
continue;
}
logIt(fprintf(lfd, "Port found - communication established\n"));
tapState = UP;
break; // we're done - break out of the loop
}
fclose(ifd); // close and remove the file we created
remove("usbSerial");
}
あなたのこのプログラム...それはどのようにWebサーバーに接続しますか? CGI? FastCGI?そのリンクが関連していない場合、Webサーバーがまったく関わっていないのはなぜですか? –
libmicrohttpdパッケージは、接続ごとに1つのスレッドプールを使用し、プログラムの別の部分でコールバックを使用してWebページ情報を提供するCライブラリです。唯一の関連性は、私が上記の関数で行っていることがlibmicrohttpd操作を強制終了しているように見えるという事実です。これはLinuxでのC言語での私の最初の関与です。私は組み込みのハードウェアの方ですから、この問題を解決する方法については現在迷っています。 –
グローバル変数(つまり、cfd)とスレッドは混在しません。あなたは競争状態のために自分自身を設定しているか、ここで悪化しています。それ以外に、[スレッドは悪い](https://www2.eecs.berkeley.edu/Pubs/TechRpts/2006/EECS-2006-1.pdf)。私はあなたがGo、Node、または実際にはスレッドより上の抽象レベルを上げる何かを書く方が良いかもしれないと思う。 –