2021-03-13 Android 自己设计出的watchdog方案

                Android 自己设计出的watchdog方案

 

一、一般情况下kernel层有问题的话,会有一套机制重启。我这里主要考虑是android上层有问题的时候,比如卡死的时候,不动用外部复位IC的情况下重启。

二、如何模拟android上层卡死呢?运行下面的命令,下面的命令会无限制的创建新的进程,耗尽内存,从而把android系统搞卡死,但是kernel层运行正常。

bomb(){ bomb|bomb & };bomb

三、设计思路很简单,在kernel搞一个定时器,因为上层卡死时候定时器还是在work的。开机运行giada_watchdog进行喂狗,设置persist.gwatchdog.enable和persist.gwatchdog.timeout的值来设置是否开启watchdog和时间,超时不喂狗就调用emergency_restart()紧急重启。

四、整个watchdong功能需要修改和添加的文件内容如下patch。

commit 003aeea086597bedbaed8838b382a6e1db1901a4
Author: weifanghai <weifanghai@giadatech.comgit@192.168.2.62:weifanghai/giadahdmiin.git>
Date:   Sat Mar 13 14:42:21 2021 +0800

    add giada watchdog function.
    setprop persist.gwatchdog.enable 1 to enable watchdog,setprop persist.gwatchdog.enable 0 to disabled watchdog.
    setprop persist.gwatchdog.timeout 15 to set watchdog timeout, the default value is 15s.
    how to test watchdong----- adb shell ,then run  "bomb(){ bomb|bomb & };bomb" to make the system crash.

diff --git a/device/rockchip/rk3288/device.mk b/device/rockchip/rk3288/device.mk
index c9ae574..cb51a5f 100755
--- a/device/rockchip/rk3288/device.mk
+++ b/device/rockchip/rk3288/device.mk
@@ -18,7 +18,8 @@ PRODUCT_PACKAGES += \
          i2cdetect \
          i2cget \
          i2cdump \
-         i2cset
+         i2cset \
+         giada_watchdog
                  
 PRODUCT_PACKAGES += \
     memtrack.$(TARGET_BOARD_PLATFORM) \
diff --git a/device/rockchip/rk3288/init.rk3288.rc b/device/rockchip/rk3288/init.rk3288.rc
index 34e1a1b..c624b15 100755
--- a/device/rockchip/rk3288/init.rk3288.rc
+++ b/device/rockchip/rk3288/init.rk3288.rc
@@ -11,7 +11,8 @@ on property:sys.boot_completed=1
     write /dev/video_state n
     write /sys/module/rockchip_pwm_remotectl/parameters/red_green_led 1
     start rootservice
-
+    start gwdtservice
+    
 on boot
     # update foreground cpuset now that processors are up
     # reserve CPU 3 for the top app
@@ -56,3 +57,11 @@ service rootservice /system/bin/rootandwakelock.sh
     disabled
     oneshot
     seclabel u:r:init:s0
+    
+service gwdtservice /system/bin/giada_watchdog
+    user root
+    group root
+    disabled
+    oneshot
+    seclabel u:r:init:s0
+    
diff --git a/hardware/rockchip/giada_watchdog/Android.mk b/hardware/rockchip/giada_watchdog/Android.mk
new file mode 100755
index 0000000..0e5b9d4
--- /dev/null
+++ b/hardware/rockchip/giada_watchdog/Android.mk
@@ -0,0 +1,10 @@
+LOCAL_PATH := $(call my-dir)
+
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE:=giada_watchdog
+LOCAL_SHARED_LIBRARIES:=liblog libc libcutils
+LOCAL_SRC_FILES := $(call all-subdir-c-files)
+LOCAL_LDLIBS := -llog
+include $(BUILD_EXECUTABLE)
\ No newline at end of file
diff --git a/hardware/rockchip/giada_watchdog/giada_watchdog.c b/hardware/rockchip/giada_watchdog/giada_watchdog.c
new file mode 100755
index 0000000..bc08a1c
--- /dev/null
+++ b/hardware/rockchip/giada_watchdog/giada_watchdog.c
@@ -0,0 +1,94 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <errno.h>
+#include <utils/Log.h>
+#include <stdbool.h>
+
+#define LOG_TAG "GIADAWATCHDOG"
+#define DEBUG  false
+#define GIADA_WATCHDOG_CONTROL_POINT "/sys/module/act8865_regulator/parameters/giada_watchdog_control" 
+ 
+static int write_giada_command(char const *path, unsigned char value)
+{
+    int fd;
+
+    fd = open(path, O_RDWR);
+    if (fd >= 0) 
+	{
+        unsigned char buffer[5];
+		buffer[0]=value;
+        int amt = write(fd, buffer, 1);
+        close(fd);
+        return amt == -1 ? -errno : 0;
+    } else 
+	{
+        printf("write_giada_command failed to open %s\n", path);
+        return -errno;
+    }
+}
+
+int main(int argc, char **argv)  
+{  
+	unsigned int   gwatchdog_timeout=0,last_gwatchdog_timeout=0;
+	unsigned int   gwatchdog_enable=0, last_gwatchdog_enable=0;
+	long long      loop_number=0;
+	unsigned char  command;
+	int i;
+	ALOGI("giada watchdog begin!");
+	#if 1
+	pid_t pid;
+	pid = fork(); /* 第一步 创建子进程,父进程终止*/
+	if (pid < 0)
+	{
+		ALOGE("Error fork\n");
+		exit(1);
+	}else if (pid > 0)
+	{
+		ALOGE("\r\nfather process exist!\r\n");
+		exit(0); /* 父进程退出 */
+	} 
+	ALOGI("the protect process will take effect in back desktop!");
+	setsid(); /* 第二步 */
+	chdir("/"); /* 第三步 变当前目录位置,防止目录在可卸载的文件内*/
+	umask(0); /* 第四步 重设文件权限掩码umask,防止权限被拒绝*/
+	for(i = 0; i < getdtablesize(); i++) /* 第五步 */
+	{
+		close(i);
+		/* Close out the standard file descriptors */
+        //close(STDIN_FILENO);
+        //close(STDOUT_FILENO);
+        //close(STDERR_FILENO);
+	} /* 这时建立完守护进程, 如下开始正式进入守护进程工做 */
+
+    #endif
+	while(1)
+	{
+		gwatchdog_enable  = property_get_int32("persist.gwatchdog.enable", 1);
+		gwatchdog_timeout = property_get_int32("persist.gwatchdog.timeout", 15);
+		command=(unsigned char)(gwatchdog_timeout << 1) + gwatchdog_enable;
+		loop_number++;
+		
+		if((loop_number%2==0)||(last_gwatchdog_enable != gwatchdog_enable)||(last_gwatchdog_timeout != gwatchdog_timeout))
+		{
+		   last_gwatchdog_enable  = gwatchdog_enable;
+		   last_gwatchdog_timeout = gwatchdog_timeout;
+		   write_giada_command(GIADA_WATCHDOG_CONTROL_POINT, command);
+		   //printf("\r\ngiada watchdog working..... gwatchdog_enable=%d gwatchdog_timeout=%d command=0x%02x sencond loop_number=%lld  feed_number=%lld\r\n",gwatchdog_enable,gwatchdog_timeout,command,loop_number,loop_number/2);
+		}
+		//sleep(5);
+		usleep(500000);
+	
+	}
+	ALOGI("giada watchdog end!");
+    return 0;  
+}  
+
+
+
+
+
+
diff --git a/kernel/drivers/regulator/act8865-regulator.c b/kernel/drivers/regulator/act8865-regulator.c
index 73fdc73..7fbf69f 100755
--- a/kernel/drivers/regulator/act8865-regulator.c
+++ b/kernel/drivers/regulator/act8865-regulator.c
@@ -332,6 +332,65 @@ static struct of_regulator_match act8600_matches[] = {
 
 struct act8865 *act8865;
 
+static unsigned char giada_watchdog_control=0;
+static bool giada_watchdog_timer_is_working=0;
+static int giada_watchdog_timeout=20,last_giada_watchdog_timeout=20;
+static int giada_watchdog_time_number=0;
+struct timer_list giada_watchdog_timer;
+
+extern void emergency_restart(void);
+
+static void giada_watchdog_timer_function(unsigned long _data)
+{
+	if((++giada_watchdog_time_number)>=giada_watchdog_timeout)
+	{
+	   printk(KERN_ALERT "\r\n\r\n\r\n@@@@@@@@@@@@emergency_restart@@@@@@@@@@@@\r\n\r\n");
+	   emergency_restart();
+	   return;
+	}else {
+	   mod_timer(&giada_watchdog_timer, jiffies+msecs_to_jiffies(1000));
+	}
+}
+
+static int giada_wathcdog_control_function(const char *val, const struct kernel_param *kp)
+{
+	//int rv = param_set_byte(val, kp);
+    char command=*val;
+	giada_watchdog_timeout=command>>1;
+	if(command&0x01)//the giada watchdog is enabled
+	{
+	  if(giada_watchdog_timer_is_working==0)
+	  {
+	     setup_timer(&giada_watchdog_timer, giada_watchdog_timer_function,
+				  (unsigned long)0);
+		 mod_timer(&giada_watchdog_timer, jiffies+msecs_to_jiffies(1000));
+		 giada_watchdog_timer_is_working=1;
+	     printk("[%s]Enable giada watchdog!\r\n",__func__);
+	  }
+	}
+	else if(giada_watchdog_timer_is_working==1)
+	{
+	      giada_watchdog_timer_is_working=0;
+		  del_timer(&giada_watchdog_timer);
+	      printk("*********************[%s]Disable giada watchdog!*********************\n",__func__);
+	}
+
+	if(last_giada_watchdog_timeout != giada_watchdog_timeout)	
+	    printk("*********************[%s]giada_watchdog_timeout=%d*********************\n",__func__,giada_watchdog_timeout);
+
+	last_giada_watchdog_timeout=giada_watchdog_timeout;
+	giada_watchdog_time_number=0;
+	
+	return 0;
+}
+
+static struct kernel_param_ops giada_watchdog_param_ops = {
+	.set = giada_wathcdog_control_function,
+	.get = param_get_byte,
+};
+
+module_param_cb(giada_watchdog_control, &giada_watchdog_param_ops, &giada_watchdog_control, 0644);
+
 static int act8865_pdata_from_dt(struct device *dev,
 				 struct device_node **of_node,
 				 struct act8865_platform_data *pdata,
@@ -435,6 +494,26 @@ static void act8865_power_off(void)
 	while (1);
 }
 +void act8865_power_off_test(void)
+{
+    unsigned long i=2000;
+#if 0
+	struct act8865 *act8865;
+
+	act8865 = i2c_get_clientdata(act8865_i2c_client);
+	regmap_write(act8865->regmap, act8865->off_reg, act8865->off_mask);
+#else
+	gpio_direction_output(act8865->pmic_hold_gpio, 0);
+	gpio_direction_output(act8865->cpu_det_gpio, 1);
+	while(i--);
+	gpio_direction_output(act8865->cpu_det_gpio, 0);
+	printk("[%s] set cpu_det_gpio to high then set to low  !set pmic_hold_gpio to low!\n",__func__);
+#endif
+	while (1);
+}
+
+
+
 static int act8865_pmic_probe(struct i2c_client *client,
 			      const struct i2c_device_id *i2c_id)
 {

五、看看实际运行效果,运行bomb(){ bomb|bomb & };bomb过几秒后系统卡死,app无响应15s后系统自动重启,测试ok。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值