项目场景:
提示:本人打算将这个问题记录作为以后面试时HR问的项目难点,并且本篇文章后面会接着完善项目难点
网页与linux板子上运行的进程的通信问题:
问题1
提示:这里描述项目中遇到的问题:
1、
使用cgiFormString("led",buf,N);
函数从网页上获取到控制信号之后,将控制信号赋值给数据结构体,然后通过 msgsnd(msgid, &msg_buf,sizeof(msg_buf)-sizeof(long),0);
函数将填充后的结构体发送出去。然后就涉及到了接收命令的Linux板子,我第一次采用在pthread_led线程中使用ftok
得到相同的key之后,然后使用msgrcv()
函数接收命令,并直接解析接收到的命令看,通过解析到的命令来直接在线程中操作硬件。代码如下
//使用相同的key来访问同一个消息队列,从而得到其中的消息
if((key = ftok("/tmp",'g')) < 0){
perror("ftok failed .\n");
exit(-1);
}
msgid = msgget(key,IPC_CREAT|IPC_EXCL|0666);
if(msgid == -1) {
if(errno == EEXIST){
msgid = msgget(key,0777);
}else{
perror("fail to msgget");
exit(1);
}
}
//循环接收来自网页cgi进程的消息,并操作硬件
while(1){
bzero(&msgbuf,sizeof(msgbuf));
printf("wait form client request...\n");
msgrcv (msgid, &msgbuf, sizeof (msgbuf) - sizeof (long), 1L, 0);
printf ("Get %ldL msg\n", msgbuf.msgtype);
printf ("text[0] = %#x\n", msgbuf.text[0]);
//操作硬件的代码
if(msgbuf.text[0] == 1){
printf("open led\n");
write(led_fd, "1", 1);
}else{
printf("close led\n");
write(led_fd, "0", 1);
}
}
close(led_fd);
close(leed_fd);
通过上述的代码虽然也能操作硬件,但是有一个致命问题就是我需要在网页上多发送几次命令才能得到硬件状态的改变,按道理说应该发一次命令,硬件状态就随即改变。
原因分析:
说明接收到消息队列的消息后随即操作硬件,这种通信并没有保护机制,只能通过不断循环来试着读取消息队列中的消息,可能会导致消息不能及时操作硬件,因此需要重新写一种有保护机制的策略。
解决方案:
因此需要重新写一种有保护机制的策略:理想情况是当我们拿到来自消息队列中的消息后,给pthread_led线程发送一个信号来激活硬件操作,这样当拿到数据之后立马就去激活硬件操作,这样就不会存在消息的丢失了。
我将接收cgi传来的命令解析放在了pthread_receive线程中,代码如下:
if((key = ftok("/tmp",'g')) < 0){
perror("ftok failed .\n");
exit(-1);
}
msgid = msgget(key,IPC_CREAT|IPC_EXCL|0666);
if(msgid == -1) {
if(errno == EEXIST){
msgid = msgget(key,0777);
}else{
perror("fail to msgget");
exit(1);
}
}
printf("pthread_client_request\n");
while(1){
bzero(&msgbuf,sizeof(msgbuf));
printf("wait form client request...\n");
msgrcv (msgid, &msgbuf, sizeof (msgbuf) - sizeof (long), 1L, 0);
printf ("Get %ldL msg\n", msgbuf.msgtype);
printf ("text[0] = %#x\n", msgbuf.text[0]);
//1L~5L为线程分类的消息类型
switch(msgbuf.msgtype){
case 1L:
printf("hello led\n");
pthread_mutex_lock(&mutex_led);
cmd_led = msgbuf.text[0];//在互斥锁中进行赋值操作更安全
pthread_mutex_unlock(&mutex_led);
pthread_cond_signal(&cond_led);
break;
case 2L://BEEP相关操作
printf("hello beep\n");
pthread_mutex_lock(&mutex_buzzer);
cmd_beep = msgbuf.text[0];
pthread_mutex_unlock(&mutex_buzzer);
pthread_cond_signal(&cond_buzzer);
break;
case 3L:
printf("hello seg\n");
break;
case 4L:
printf("hello fan\n");
break;
当上面的pthread_receive线程接收到了来自网页的命令之后,在互斥锁中对cmd_led进行赋值,这样使得操作更加安全,不会导致信息的丢失 。当赋值操作完成之后进行解锁操作,然后通过pthread_cond_signal(&cond_led)发送信号量去激活pthread_cond_wait(&cond_led,&mutex_led)函数,接着进一步去执行硬件操作代码:如下为硬件操作代码
while(1){
pthread_mutex_lock(&mutex_led);
pthread_cond_wait(&cond_led,&mutex_led);//等待条件变量的到来
printf("IN main cmd_led = %d", cmd_led);
if(cmd_led != 0){
printf("open led\n");
write(led_fd, "1", 1);
}
else{
printf("close led\n");
write(led_fd, "0", 1);
}
pthread_mutex_unlock(&mutex_led);
}
close(led_fd);
close(leed_fd);
当收到信号之后,pthread_cond_wait函数的阻塞效果解除,进一步去执行硬件操作代码
---------------------------------------------------------------问题1结束-----------------------------------------------------
问题2
2、网页上如此多的消息上传和下发,那么应该如何通过命令来控制如此多的外设吧,
解决方案
制定自己的通信协议,上层应用层通过对一个字节进行命令掩码进行赋值,然后交给其中的一个线程解析数据。
-----------------------------------------------------------------问题2结束---------------------------------------------------
问题3
3、html语言如何与C语言进行交互呢?
解决方案
在开发板上移植boa服务器,然后html语言通过cgi进程,实现与C语言的交互
问题4
4、在stm32向将结构体数据传输的时候存在的字节对齐问题?
假设遇到struct{char a; int b}这种的话,char就有三个字节的浪费,当大批量高速传输数据的话就会造成空间的浪费,所以stm32结构体中的数据取消了内存对齐
问题5
4、为什么用共享内存为什么用消息队列?