天天看點

cgi控制led,通過網絡www實作

          cgi控制6410闆子LED

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;

}

繼續閱讀