分析params_s方法

/**
     * 解析启动模式参数
     * @param $opt
     */
    static public function params_s($opt)
    {
        //判断传入了s参数但是值,则提示错误
        if ((isset($opt["s"]) && !$opt["s"]) || (isset($opt["s"]) && !in_array($opt["s"], array("start", "stop", "restart")))) {
            Main::log_write("Please run: path/to/php main.php -s [start|stop|restart]");
        }

        if (isset($opt["s"]) && in_array($opt["s"], array("start", "stop", "restart"))) {
            switch ($opt["s"]) {
                case "start":
                    Crontab::start();
                    break;
                case "stop":
                    Crontab::stop();
                    break;
                case "restart":
                    Crontab::restart();
                    break;
            }
        }
    }

 这里我们先分析Crontab::start()

  从这个意思我们应该知道这应该是进程启动的方法

  因为crontab自己注册了引入方法,所以方法在include/Crontab.class.php中

/**
     * 启动
     */
    static public function start()
    {
        if (file_exists(self::$pid_file)) {
            die("Pid文件已存在!
");
        }
        self::daemon();
        self::set_process_name();
        self::run();
        Main::log_write("启动成功");
    }

  先检查pid文件是否存在,如果存在说明进程已经启动不能再次开始

      self::daemon(); 在上一节,如果params_d($opt) 开启守护进程会执行swoole_process::daemon();//传送门:https://wiki.swoole.com/wiki/page/273.html

      self::set_process_name();//设置进程名字 这里没有支持用户自己命名,名字为:lzm_Master

  接下来执行run方法:

  

 /**
     * 运行
     */
    static protected function run()
    {
        self::$tasksHandle = new LoadTasks(strtolower(self::$taskType), self::$taskParams);
        self::register_signal();
        if (self::$checktime) {
            $run = true;
            Main::log_write("正在启动...");
            while ($run) {
                $s = date("s");
                if ($s == 0) {

                    Crontab::load_config();
                    self::register_timer();
                    $run = false;
                } else {
                    Main::log_write("启动倒计时 " . (60 - $s) . " 秒");
                    sleep(1);
                }
            }
        } else {
            self::load_config();
            self::register_timer();
        }
        self::get_pid();
        self::write_pid();
        //开启worker
        if (self::$worker) {
            (new Worker())->loadWorker();
        }
    }

  106行:self::$tasksHandle = new LoadTasks(strtolower(self::$taskType), self::$taskParams);//这里我们就分析LoadTasksByFile,这里放到下一讲

  107行:self::register_signal();//注册信号,用来处理进程退出

       如果在客户端进行ctrl+c退出的话,会发送SIGINT信号,但是这里没做处理,那么请不要在客户端直接ctrl+c退出程序,不然的话下次就需要执行重启命令了,因为不退出

  如果受到退出信号SIGTERM就会直接调用exit2p:删除掉pid文件然后直接exit退出

       还需要处理当子进程退出,为了不让程序变成僵尸进程需要进行wait处理

  这里是先判断是否在tasklist中pid是否存在,如果存在这个任务,则直接将子进程关闭,如果这个任务还有unique_list值(这里是任务里的排他数量的意思)会进行自减,杀死后扣除1,如果在load_config中会继续往taskTabel插入任务,争用这个unique字段
       如果是工作进程,那么复制一份work进程

  至于SIGUSR1信号,这里本来是应该是重新加载配置文件的,不知道为什么这里没有加上实现

/**
     * 注册信号
     */
    static private function register_signal()
    {
        swoole_process::signal(SIGTERM, function ($signo) {
            self::exit2p("收到退出信号,退出主进程");
        });
        swoole_process::signal(SIGCHLD, function ($signo) {
            while ($ret = swoole_process::wait(false)) {
                $pid = $ret['pid'];
                if (isset(self::$task_list[$pid])) {
                    $task = self::$task_list[$pid];
                    if ($task["type"] == "crontab") {
                        $end = microtime(true);
                        $start = $task["start"];
                        $id = $task["id"];
                        Main::log_write("{$id} [Runtime:" . sprintf("%0.6f", $end - $start) . "]");
                        $task["process"]->close();//关闭进程
                        unset(self::$task_list[$pid]);
                        if (isset(self::$unique_list[$id]) && self::$unique_list[$id] > 0) {
                            self::$unique_list[$id]--;
                        }
                    }
                    if ($task["type"] == "worker") {
                        $end = microtime(true);
                        $start = $task["start"];
                        $classname = $task["classname"];
                        Main::log_write("{$classname}_{$task["number"]} [Runtime:" . sprintf("%0.6f", $end - $start) . "]");
                        $task["process"]->close();//关闭进程
                        (new Worker())->create_process($classname, $task["number"], $task["redis"]);
                    }
                }
            };
        });
        swoole_process::signal(SIGUSR1, function ($signo) {
            //TODO something
        });

    }

  这些都执行后,会执行Crontab::load_config();

      该方法会读取到我们配置文件的读取路径中的数据,在main.php里面params_c方法会默认从ROOT_PATH . "config/crontab.php"中获取

  Crontab.class.php:line162->ParseCrontab::parse($task["rule"], $time);//这里是解析定时任务的规则返回值是每个任务的下次执行的间隔(秒级),类似linux自带的crontab的规则,这个放到后面讲解

  TickTable::set_task($ret, array_merge($task, array("id" => $id)));//这里会将读取到任务的规则写到ticktable里面
  self::register_timer();//这里才是任务调度的关键,每隔1分钟会将到下一分钟需要执行的任务插入到ticktable里面,然后每隔1s钟执行task

下一讲:do_something方法
原文地址:https://www.cnblogs.com/gavinjunftd/p/8080268.html