目录
线程相关API的复习和代码分析
cgic的代码分析
客户端请求线程的编写
ftok()函数深度解析_satellite13的博客-CSDN博客
消息队列函数四个组成函数:msgget、msgctl、msgsnd、msgrcv_New_bee_xu的博客-CSDN博客
先来复习一下线程相关的API函数
key_t ftok(const char *pathname, int proj_id);
其中参数fname是指定的文件名,这个文件必须是存在的而且可以访问的。id是子序号,它是一个8bit的整数。即范围是0~255。当函数执行成功,则会返回key_t键值,否则返回-1。在一般的UNIX中,通常是将文件的索引节点取出,然后在前面加上子序号就得到key_t的值。
if((key = ftok("/tmp",'g')) < 0){
perror("ftok failed .\n");
exit(-1);
}
根目录下的tmp是系统临时文件系统会自动清理
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);
}
}
msgget(得到消息队列标识符或创建一个消息队列对象) |
||
所需头文件 |
#include #include #include |
|
函数说明 |
得到消息队列标识符或创建一个消息队列对象并返回消息队列标识符 |
|
函数原型 |
int msgget(key_t key, int msgflg) |
|
函数传入值 |
key |
0(IPC_PRIVATE):会建立新的消息队列 |
大于0的32位整数:视参数msgflg来确定操作。通常要求此值来源于ftok返回的IPC键值 |
||
msgflg |
0:取消息队列标识符,若不存在则函数会报错 |
|
IPC_CREAT:当msgflg&IPC_CREAT为真时,如果内核中不存在键值与key相等的消息队列,则新建一个消息队列;如果存在这样的消息队列,返回此消息队列的标识符 |
||
IPC_CREAT|IPC_EXCL:如果内核中不存在键值与key相等的消息队列,则新建一个消息队列;如果存在这样的消息队列则报错 |
||
函数返回值 |
成功:返回消息队列的标识符 |
|
出错:-1,错误原因存于error中 |
||
附加说明 |
上述msgflg参数为模式标志参数,使用时需要与IPC对象存取权限(如0600)进行|运算来确定消息队列的存取权限 |
|
错误代码 |
EACCES:指定的消息队列已存在,但调用进程没有权限访问它 EEXIST:key指定的消息队列已存在,而msgflg中同时指定IPC_CREAT和IPC_EXCL标志 ENOENT:key指定的消息队列不存在同时msgflg中没有指定IPC_CREAT标志 ENOMEM:需要建立消息队列,但内存不足 ENOSPC:需要建立消息队列,但已达到系统的限制 |
msgrcv (从消息队列读取消息) |
||
所需头文件 |
#include #include #include |
|
函数说明 |
从标识符为msqid的消息队列读取消息并存于msgp中,读取后把此消息从消息队列中删除 |
|
函数原型 |
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); |
|
函数传入值 |
msqid |
消息队列标识符 |
msgp |
存放消息的结构体,结构体类型要与msgsnd函数发送的类型相同 |
|
msgsz |
要接收消息的大小,不含消息类型占用的4个字节 |
|
msgtyp |
0:接收第一个消息 |
|
>0:接收类型等于msgtyp的第一个消息 |
||
<0:接收类型等于或者小于msgtyp绝对值的第一个消息 |
||
msgflg |
0: 阻塞式接收消息,没有该类型的消息msgrcv函数一直阻塞等待 |
|
IPC_NOWAIT:如果没有返回条件的消息调用立即返回,此时错误码为ENOMSG |
||
IPC_EXCEPT:与msgtype配合使用返回队列中第一个类型不为msgtype的消息 |
||
IPC_NOERROR:如果队列中满足条件的消息内容大于所请求的size字节,则把该消息截断,截断部分将被丢弃 |
||
函数返回值 |
成功:实际读取到的消息数据长度 |
|
出错:-1,错误原因存于error中 |
||
错误代码 |
E2BIG:消息数据长度大于msgsz而msgflag没有设置IPC_NOERROR EIDRM:标识符为msqid的消息队列已被删除 EACCESS:无权限读取该消息队列 EFAULT:参数msgp指向无效的内存地址 ENOMSG:参数msgflg设为IPC_NOWAIT,而消息队列中无消息可读 EINTR:等待读取队列内的消息情况下被信号中断 |
msgrcv()解除阻塞的条件有以下三个:
① 消息队列中有了满足条件的消息。
② msqid代表的消息队列被删除。
③ 调用msgrcv()的进程被信号中断。
msgrcv (msgid, &msgbuf, sizeof (msgbuf) - sizeof (long), 1L, 0);
读取html传过来的long型数据确定要控制什么
然后再判断具体操作
消息就是从cgic传来的
函数的作用是将域名为第一个参数的N-1个字节的字符copy到buf缓冲区中。
这块学的不怎么好,也很少用。
现在网页主要是是java写。这个框架就是给我们搞个测试,这是我的感觉。
这块后面单独说吧。
消息类型的分配:
1L: LED控制
2L: 蜂鸣器控制
3L: 窗户控制
4L: 扇热加热控制
5L: 温湿度最值设置
6L: 保留机器人控制
7L-8L-9L,
10L: GSM报警控制
先按照这个完善一下我们的客户端请求
#include "data_global.h"
#include "chrdev.h"
#include
#define CMDBUF_SIZE 8
extern pthread_mutex_t mutex_led;
extern pthread_cond_t cond_led;
extern unsigned char cmd_seg;
int fswaterled_control(int led_fd, int times);
int fsled_control(int led_fd, unsigned char led_control_cmd); //发送的数字
int fsled_close_all(int led_fd);
int fsled_open_all(int led_fd)
//:A9LED模块线程.
void *pthread_led(void *arg)
{
printf("pthread_led\n");
int i, j;
int led_fd;
led_desc_t led;//LED结构体
led_fd = open(LED_DEV, O_RDWR);
zigbee_fd = open(ZIGBEE_DEV, O_RDWR);
if(led_fd == -1){
printf("A9LED open failed.\n");
}
if(zigbee_fd == -1){
printf("ZIGBEE LED open failed.\n");
}
printf("led_fd ;%d.\n",led_fd);
printf("zigbee_fd ;%d.\n",zigbee_fd);
char cmdbuf[CMDBUF_SIZE] = {0};
while(1){
pthread_mutex_lock(&mutex_led);
pthread_cond_wait(&cond_led,&mutex_led);
printf("led ioctl:***********\n");
// fswaterled_control(led_fd,2); //流水灯
if(cmd_led == 0x41){
fswaterled_control(led_fd,2); //流水灯
}else if(cmd_led == 0x00){
fsled_close_all(led_fd); //关闭a9
strcpy(cmdbuf,"@LE00000\n"); //注意点
write(zigbee_fd,cmdbuf, sizeof(cmdbuf)/sizeof(cmdbuf[0]));//关闭zigbee中的LED
sleep(2);
}else if(cmd_led == 0xFF){
fsled_open_all(led_fd);
strcpy(cmdbuf,"@LE00001\n"); //注意点
write(zigbee_fd,cmdbuf, sizeof(cmdbuf)/sizeof(cmdbuf[0]));
sleep(2);
}else if(cmd_led == 0xF0){
fsled_close_all(led_fd);
strcpy(cmdbuf,"@LE00002\n"); //注意点
write(zigbee_fd,cmdbuf, sizeof(cmdbuf)/sizeof(cmdbuf[0]));
sleep(2);
}else if(cmd_led == 0x55){
fsled_close_all(led_fd);
strcpy(cmdbuf,"@LE00003\n"); //注意点
write(zigbee_fd,cmdbuf, sizeof(cmdbuf)/sizeof(cmdbuf[0]));
sleep(2);
}
pthread_mutex_unlock(&mutex_led);
}
close(led_fd);
close(zigbee_fd);
}
int fsled_control(int led_fd, unsigned char led_control_cmd)
{
int i = 0;
led_desc_t led;
led_control_cmd &= 0x0f;
int shift_count = 1; //第0位,第1 - 3位
printf("led_control_cmd = %d.\n",led_control_cmd);
fsled_close_all(led_fd);
sleep(3);
while(led_control_cmd){
if(shift_count >= 5)
break;
if((led_control_cmd & 0x1) == 1){ //第0位开始 = LED2
shift_count ++; // = 2 LED2
printf("if shift_count :%d.\n",shift_count);
led.which = shift_count; //led2 3 4 5 灯
ioctl(led_fd,FSLEDON,&led);
usleep(50000); //让驱动响应的时间
}else {
shift_count ++;
printf("else shift_count :%d.\n",shift_count);
led.which = shift_count; //led2 3 4 5 灯
ioctl(led_fd,FSLEDOFF,&led);
usleep(50000);
}
led_control_cmd >>= 1;
}
return 0;
}
int fsled_close_all(int led_fd)
{
int i = 0;
led_desc_t led;
for(i = 2;i < 6;i ++){
led.which = i;
ioctl(led_fd,FSLEDOFF,&led);
usleep(50000);
}
return 0;
}
int fsled_open_all(int led_fd)
{
int i = 0;
led_desc_t led;
for(i = 2;i < 6;i ++){
led.which = i;
ioctl(led_fd,FSLEDON,&led);
usleep(50000);
}
return 0;
}
int fswaterled_control(int led_fd, int times)
{
int i = 0,j = 0;
led_desc_t led;
for(j = 0;j < times;j ++){
for(i = 2;i < 6;i ++){
led.which = i;
ioctl(led_fd,FSLEDON,&led);
usleep(500000);
led.which = i;
ioctl(led_fd,FSLEDOFF,&led);
usleep(500000);
}
}
return 0;
}
先改成这样
后米优化在说
#ifndef __CHRDEV_H_
#define __CHRDEV_H_
typedef struct led_desc{
int which; //哪一个
int state; //状态
}led_desc_t;
#define mytype 'f'
#define FSLEDON _IOW(mytype,1,led_desc_t)
#define FSLEDOFF _IOW(mytype,0,led_desc_t)
#endif
#ifndef __DATA_GLOBAL__H__
#define __DATA_GLOBAL__H__
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*********************************************************
data_global.h :
È«ŸÖµÄºê¶šÒå#define
È«ŸÖµÄÏ̺߳¯ÊýÉùÃ÷
È«ŸÖµÄÉ豞œÚµãÉùÃ÷
È«ŸÖµÄÏûÏ¢¶ÓÁз¢Ëͺ¯ÊýÍⲿexternÉùÃ÷
È«ŸÖµÄÏûÏ¢¶ÓÁÐŽ«µÝµÄœá¹¹ÌåÐÅÏ¢ÉùÃ÷
*********************************************************/
/*********************************************************
È«ŸÖµÄºê¶šÒå
*********************************************************/
#define MONITOR_NUM 1
#define QUEUE_MSG_LEN 32
#define ZIGBEE_DEV "/dev/ttyUSB0"
#define BEEPER_DEV "/dev/fsbeeper0"
#define LED_DEV "/dev/fsled0"
unsigned char cmd_led;
unsigned char cmd_buzzer;
unsigned char cmd_seg;
unsigned char cmd_fan;
unsigned char cmd_sms;
/*********************************************************
È«ŸÖµÄœá¹¹ÌåÉùÃ÷
*********************************************************/
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
struct zigbee_info{
uint8_t head; // 标识位 @作为一条消息的头 #作为一条指令的头
uint8_t demo; // 货物的流向: 入库i 出库 o
uint8_t device[2]; // 设备类型
uint8_t device_id[4]; // 设备id
float humidity; // 湿度
float temperature; // 温度
float tempMIN; // 温度下限
float tempMAX; // 温度上限
float humidityMIN; // 湿度下限
float humidityMAX; // 湿度上限
float smokescope; // 烟雾浓度
float precipitation; // 降雨量
uint8_t fire[2]; // 火灾地点
uint8_t RFID[8]; // RFID的ID
uint8_t reserved_char[2]; // 预留
uint32_t reservef_int[3]; // 预留
};
//消息队列结构体
struct msg{
uint8_t head; // 标识位 @作为一条消息的头 #作为一条指令的头
uint8_t ctrl; // 控制指令
uint8_t device[2]; // 设备类型
uint8_t device_id[4]; // 设备id
uint8_t test[QUEUE_MSG_LEN]; // 消息正文
};
/*********************************************************
È«ŸÖµÄÍⲿÏ̺߳¯ÊýÉùÃ÷
*********************************************************/
extern void *pthread_client_request (void *arg); //œÓÊÕCGI µÈµÄÇëÇó
extern void *pthread_refresh(void *arg); //ˢй²ÏíÄÚŽæÊýŸÝÏß³Ì
extern void *pthread_sqlite(void *arg); //ÊýŸÝ¿âỊ̈߳¬±£ŽæÊýŸÝ¿âµÄÊýŸÝ
extern void *pthread_transfer(void *arg); //œÓÊÕZigBeeµÄÊýŸÝ²¢œâÎö
extern void *pthread_sms(void *arg); //·¢ËͶÌÐÅÏß³Ì
extern void *pthread_buzzer(void *arg); //·äÃùÆ÷¿ØÖÆÏß³Ì
extern void *pthread_led(void *arg); //ledµÆ¿ØÖÆÏß³Ì
extern int send_msg_queue(long type,unsigned char text);
/*********************************************************
È«ŸÖµÄÏûÏ¢¶ÓÁÐŽ«µÝµÄœá¹¹ÌåÉùÃ÷
*********************************************************/
//ÏûÏ¢¶ÓÁМṹÌå
struct msg
{
long type;//ŽÓÏûÏ¢¶ÓÁÐœÓÊÕÏûϢʱÓÃÓÚÅжϵÄÏûÏ¢ÀàÐÍ
long msgtype;//ŸßÌåµÄÏûÏ¢ÀàÐÍ
unsigned char text[QUEUE_MSG_LEN];//ÏûÏ¢ÕýÎÄ
};
#endif
后面就不这样写了,改代码就是牵一发动全身。所以不具体改某块只记录每天做了什么