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; } |