4月「掘金·日新计划」第29天
四、守护进程udev
守护智能家居进程(意外退出重启进程)
-
生存周期长[非必须],一般操作系统启动的时候就启动,关闭的时候关闭。
-
守护进程和终端无关联,也就是他们没有控制终端,所以当控制终端退出,也不会导致守护进程退出
-
守护进程是在后台运行,不会占着终端,终端可以执行其他命令
-
一个守护进程的父进程是init进程,因为它真正的父进程在fork出子进程后就先于子进程exit退出了,所以它是一个由init继承的孤儿进程
-
代码演示
#include <unistd.h> #include <signal.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <sys/stat.h> #include <time.h> #include <stdio.h> #include <stdbool.h> static bool flag = true; void handler(int sig) { printf("I got a signal %d\nI'm quitting.\n", sig); flag = false; } int judMent() { FILE *file; char buffer[128] = {'\0'}; char *cmd = "ps -elf |grep SmartHome|grep -v grep"; file = popen(cmd, "r"); fgets(buffer, 128, file); if(strstr(buffer, "SmartHome") != NULL){ return 0; }else{ return -1; } printf("BUFFER:%s\n",buffer); } int main() { time_t t; int fd; //创建守护进程 if(-1 == daemon(0, 0)){ printf("daemon error\n"); exit(1); } //设置信号处理函数 struct sigaction act; act.sa_handler = handler; sigemptyset(&act.sa_mask); act.sa_flags = 0; if(sigaction(SIGQUIT, &act, NULL)){ printf("sigaction error.\n"); exit(0); } sleep(30); //进程工作内容 while(flag){ if( judMent() == -1){ system("/home/pi/SmartHome &"); } sleep(5); } return 0; }
五、监控视频储存
-
树莓派摄像头可以使用的2个库
- mjpg-streamer(网页显示监视画面)
- motion(提供网络摄像头的功能。当拍摄过程中画面发生变动时,Motion可以保存动作发生时的图片和视频)
-
mjpg-streamer
-
开启网页显示监视画面
- 运行脚本:MjpgStreamer/mjpg-streamer/mjpg-streamer-experimental/start.sh
-
拍照
-
raspistill -o image.jpg -t 1000
- -w, –width : 设置图像宽度 <尺寸> -h, –height : 设置图像高度 <尺寸> -q, –quality : 设置jpeg品质 <0到100> -t, –timeout : 拍照和关闭时的延时指定,未指定时默认是5s,毫秒为单位,1000便表示1秒 -o, –output : 输出文件名 <文件名>,如果要写到stdout,使用-o -,如果不特别指定,图像文件不会被保存 -rot:图像旋转角度,只支持 0、90、180、270 度
-
wget http://192.168.43.207:8080/?action=snapshot -O ./a.jpg
-
-
视频储存
-
raspivid -o b.h264 -t 10000 -w 1280 -h 720
- 录制一段十秒钟的名为b.h264的视频,且分辨率为1280x720
-
-
转mp4格式
- 安装:sudo apt-get install gpac
- MP4Box -fps 30 -add b.h264 b.mp4(每秒30帧)
-
六、遇到的问题和未解决的问题
-
驱动部分
-
改一个IO,另一个IO也变了(5可以单独改。改4, 5引脚也会变)
-
解决:加一个中间变量,直接赋值
-
因为寄存器值不一定,所以前面可能是乱的
- 例如寄存器的值是10101011101
- 要给01重新写入11,但是用|=的话,就会把本来其他值(乱值)也赋进去,造成乱了
-
-
-
应用层
-
给APP传cpu温度和火灾检测,传过去值乱了
-
解决:将错就错,增加把数16777216当1用
-
因为存在一个字节序问题,树莓派传过去的值大小端就反过来了
- app端,字符串可以成功解析出来,int类型解析不出来
- 解决方法,要么树莓派端把数反过来在发送,要么APP端将错就错
-
-
bind: Address already in use(端口占用)
-
服务器先退出,下一次启用服务器会端口占用
-
解决:
if(setsockopt(s_fd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(int)) < 0){ //解决bind,端口占用问题 perror("setsockopt"); goto Sfd; } -
SO_REUSEADDR可以让当前的端口立即重用
-
在服务端终止之后,会有一个TIME_WAIT的状态,再次打开会出现:bind的
但是,服务器端可以尽可能的使用REUSEADDR(在绑定之前尽可能调用setsockopt来设置REUSEADDR)套接字选项,这样就可以使得不必等待TIME_WAIT状态就可以重启服务器了,也就是说:TIME_WAIT状态还是存在的,但是不影响我们重新启动服务器 -
CTRL+C结束时,出现了TIME_WAIT,2-4分钟后释放
-
CTRL+Z结束时,出现的是ESTABLISHED,永久,除非杀死进程
-
-
-
摄像头切换功能,需要杀死相应进程
-
ps -ef | grep 进程名| grep -v grep | grep -v mca |awk '{print $2}' | xargs kill -9
-
ps -ef 表示查看全格式的全部进程。此处用-A也行:显示所有程序
grep 是过滤
grep -v 是反过滤,就是不要把它顾虑出来
print 是打印
$2 是第二列,也就是进程的ID
awk 是对于文件中一行行的独处来执行操作 。
awk '{print $2}' 是把每一行的第二列(进程ID)打印出来
| xargs 是将"|" 前面获取到的进程号通过空格分割,传递给kill -9,将这些进程全部杀死 原文链接:blog.csdn.net/u011736532/…
-
-
-
安卓APP
-
内网穿透,粘包
-
服务器(树莓派)发送的数据会被当成一个数据发送(粘包)
-
客户端(安卓APP)接收数据出错
- 解决方法:因为是固定数据大小,所以直接拿到后按字节拆包
-
-
-
未解决
-
在人脸识别的时候,继续输入人脸识别命令会阻塞(在人脸识别完成之前app或uart端无法继续输入)
- 解决方法:fork一个进程去等待上一个命令处理完成(无法做到)
- fork后,互斥锁被复制了2份,不在是同一个锁,导致线程间同步无法完成
-
外网访问,手机APP控制会有延迟(控制和灯锁显示都有,控制延迟小点)
-