cgi意思为通用网关接口,是服务器与浏览器动作相互通信的一种方式和桥梁。我们通过浏览器网页收集动作并触发cgi程序可以处理自己在cgi程序中定义的需要处理的过程。
这里写了一个简单的通过网页控制目标板LED的程序,进程间通信方式为共享内存,有点铺张,可以使用FIFO更简单,但是追求的就是一个折腾的过程,于是乎各种蛋疼菊紧扑面而来,还好最后以极强的心理战术解决困境。花了一天时间啊!!!(初学留个记录,看以后回过来头再看有多可笑)
指的提醒的是IPC机制中的信号量是不会随进程结束而自动消除的,除非进程中自己有显示的消除,不然任何进程都可以用,不管其中是否由退出的,只要不删除都可以用,共享内存也是一样。
以下是led对应的接收cgi数据的程序:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/ioctl.h>
#include<sys/sem.h>
#include<sys/shm.h>
#include<sys/ipc.h>
#define LED_ON 1
#define LED_OFF 0
int main(int argc, char **argv)
{
int fd = -1;
unsigned int led_no;
struct sembuf sem_led;
int semid,shmid,i=0,val;
char *shmdat_r,led_status[3];
int position;
sem_led.sem_num = 0;
fd = open("/dev/s3c6410leds",0);
if(fd<0)
{
printf("Can not open device leds\n");
return -1;
}
semid=semget((key_t)12345,1,0666|IPC_CREAT);
if(semid==-1) {
printf("sem get error\n");
return -1;
}
if(semctl(semid,0,SETVAL,0)==-1) {
printf("sem set val error\n");
return -1;
}
shmid=shmget((key_t)54321,512,0666|IPC_CREAT);
if(shmid==-1) {
printf("shm get error \n");
return -1;
}
shmdat_r = shmat(shmid,NULL,0);
if(shmdat_r==NULL) {
printf("shm map error\n");
if(shmctl(shmid,IPC_RMID,NULL)==-1) {
printf("rm shm error\n");
return -1;
}
return -1;
}
printf("shamdat:%s\n",shmdat_r);
while(1) {
if((val=semctl(semid,0,GETVAL))==1) {
printf("%s\n",shmdat_r);
led_no = *shmdat_r-'0'-1;
printf("ledno=%d\n",led_no);
shmdat_r++;//在这里内存地址加1,由于进程不会退出,是一个无限循环的过程,所以后面要记得减1
if(!strcmp(shmdat_r,"ON"))
{
ioctl(fd,LED_ON,led_no);
}
else if(!strcmp(shmdat_r,"OFF"))
{
ioctl(fd,LED_OFF,led_no);
}
shmdat_r--;//这里内存地址减1,对应的前面的加1,以保护现场,不至于一直往后移
sem_led.sem_op = -1;
if(semop(semid,&sem_led,1)==-1) {
printf("sem -1 failed\n");
return -1;
}
}
}
close(fd);
shmdt(shmdat_r);
printf("removing the shm\n");
if(shmctl(shmid,IPC_RMID,0)!=0) {
printf("remove shm error\n");
return -1;
}
if(semctl(semid,0,IPC_RMID,0)!=0) {
printf("rm sem error\n");
return -1;
}
printf("deleting the sem\n");
return 0;
err:
if(fd>0) close(fd);
return -1;
}
以下是cgi程序:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/shm.h>
#include<sys/sem.h>
#include<sys/ipc.h>
//打印网页信息的头
void print_head(void)
{
printf("Content-type: text/html\n\n");
printf("<html>\n");
printf("<head><title>CGI Output</title></head>\n");
printf("<body>\n");
}
//打印网页信息的尾
void print_tail(void)
{
printf("<body>\n");
printf("</html>\n");
}
int main(void)
{
char *input_tmp,inputstr[30],*method,tmp1[20],tmp2[20],tmp3[20];
int i=0,ledno,length;
struct sembuf sem_led;
int semid,shmid,val;
char *shmdat;
sem_led.sem_num = 0;
method=getenv("REQUEST_METHOD");
input_tmp=getenv("QUERY_STRING");
//以下开始对数据进行URL解码
while(*input_tmp!='\0') {
if(*input_tmp=='%') {
inputstr[i]='\0';
break;
}
else {
inputstr[i] = *input_tmp;
input_tmp++;
i++;
}
}
length = i;
inputstr[length] = '\0';
i = 0;
sscanf(inputstr,"%[^&]",tmp1);
while(tmp1[i]!='\0') i++;
length = i;
i = 0;
ledno = tmp1[length-1];
while(inputstr[i+length+1]!='\0') {
tmp2[i] = inputstr[i+length+1];
i++;
}
length = i;
tmp2[length] = '\0';
i = 0;
sscanf(tmp2,"%[^&]",tmp2);
sscanf(tmp2,"%[^=]",tmp3);
while(tmp3[i]!='\0') i++;
length = i;
i = 0;
while(tmp2[i+length+1]!='\0') {
tmp3[i] = tmp2[i+length+1];
i++;
}
length = i;
tmp3[length]='\0';
i = 0;
//到此结束对数据URL解码
semid=semget((key_t)12345,1,0666|IPC_CREAT);
if(semid==-1) {
printf("sem get error\n");
return -1;
}
if(semctl(semid,0,SETVAL,0)==-1) {
printf("sem set val error\n");
return -1;
}
shmid=shmget((key_t)54321,512,0666|IPC_CREAT);
if(shmid==-1) {
printf("shm get error \n");
return -1;
}
shmdat = shmat(shmid,NULL,0);
if(shmdat==NULL) {
printf("shm map error\n");
if(shmctl(shmid,IPC_RMID,NULL)==-1) {
printf("rm shm error\n");
return -1;
}
return -1;
}
print_head();
printf("<h1>method:%s</h1>\n",method);
printf("<h1>inputstr:%s</h1>\n",inputstr);
printf("<h1>tmp1:%s</h1>\n",tmp1);
printf("<h1>tmp2:%s</h1>\n",tmp2);
printf("<h1>ledno=%d</h1>\n",(ledno-'0'));
printf("<h1>status=%s</h1>\n",tmp3);
print_tail();
if((val=semctl(semid,0,GETVAL))==0) {
print_head();
printf("<h1>sem val 0<h1>\n");
print_tail();
*shmdat = ledno;
shmdat++;
while(tmp3[i]!='\0') {
*shmdat = tmp3[i];
shmdat++;
i++;
}
*shmdat='\0'; //由于可能出现ON,OFF字符长度不一的情况,这里需要及时在结尾加上字符串结束符
i=0;
sem_led.sem_op = 1;
if(semop(semid,&sem_led,1)==-1) {
print_head();
printf("<h1>sem +1 error<h1>\n");
print_tail();
return -1;
}
val=semctl(semid,0,GETVAL);
print_head();
printf("<h1>sem val %d<h1>\n",val);
print_tail();
}
return 0;
}
|