Contents

ARST打卡第139周[139/521]

Algorithm

lc390_消除游戏

模拟,或者找规律,应该是找规律

模拟找规律: 巧妙利用每次左边界跳动的值。处理好数组中还剩的数组数,以及相邻数之差 https://leetcode-cn.com/problems/elimination-game/solution/xiao-chu-you-xi-by-leetcode-solution-ydpb/

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class Solution {
public:
    int lastRemaining(int n) {
        int a1 = 1;
        int k = 0, cnt = n, step = 1;
        while (cnt > 1) {
            if (k % 2 == 0) { // 正向
                a1 = a1 + step;
            } else { // 反向
                a1 = (cnt % 2 == 0) ? a1 : a1 + step;
            }
            k++;
            cnt = cnt >> 1;
            step = step << 1;
        }
        return a1;
    }
};

Review

raft选举和提交动画

http://thesecretlivesofdata.com/raft/

生动有趣得讲述了raft协议

Tips

SO_REUSEADDR的使用

Share-vsftpd的vsf_two_process_start源码分析

common

父子进程之间通过priv_sock_login.h 中定义的模块来进行通信,然后进行处理

子进程

  • 所以进入vsf_two_process_start(&the_session);

  • 子进程处理一些命令,然后等待检测父进程那边是否登录成功,成功则退出,或者ssl_slave

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void
vsf_two_process_login(struct vsf_session* p_sess,
                      const struct mystr* p_pass_str)
{
  char result;
  priv_sock_send_cmd(p_sess->child_fd, PRIV_SOCK_LOGIN);
  priv_sock_send_str(p_sess->child_fd, &p_sess->user_str);
  priv_sock_send_str(p_sess->child_fd, p_pass_str);
  priv_sock_send_int(p_sess->child_fd, p_sess->control_use_ssl);
  priv_sock_send_int(p_sess->child_fd, p_sess->data_use_ssl);
  result = priv_sock_get_result(p_sess->child_fd);
  if (result == PRIV_SOCK_RESULT_OK)
  {
    /* Miracle. We don't emit the success message here. That is left to
     * process_post_login().
     * Exit normally, unless we are remaining as the SSL read / write child.
     */
    if (!p_sess->control_use_ssl)
    {
      vsf_sysutil_exit(0);
    }
    else
    {
      ssl_slave(p_sess);
    }
    /* NOTREACHED */
  }
  // ...
}
  • 父进程登录成功之后,就数据传输

父进程process_login_req

父进程进行while处理登录尝试

1
2
3
4
5
/* Parent - go into pre-login parent process mode */
while (1)
{
  process_login_req(p_sess);
}

然后从父子进程socket上的父fd读取子进程那边传来的ACCT,PASS等等信息,然后进行登录处理

1
2
3
4
cmd = priv_sock_get_cmd(p_sess->parent_fd);
priv_sock_get_str(p_sess->parent_fd, &p_sess->user_str);
priv_sock_get_str(p_sess->parent_fd, &password_str);
e_login_result = vsf_privop_do_login(p_sess, &password_str);

其中 common_do_login中的第一句就是给子进程发送一个登录成功的信息,让子进程进入下一个阶段

并且如果是没有使用ssl,则等待子进程退出,否则就是ssl_slave

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
static void
common_do_login(struct vsf_session* p_sess, const struct mystr* p_user_str,
                int do_chroot, int anon)
{
  int was_anon = anon;
  const struct mystr* p_orig_user_str = p_user_str;
  int newpid;
  vsf_sysutil_install_null_sighandler(kVSFSysUtilSigCHLD);
  /* Tells the pre-login child all is OK (it may exit in response) */
  priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_OK);
  if (!p_sess->control_use_ssl)
  {
    (void) vsf_sysutil_wait();
  }
  else
  {
    p_sess->ssl_slave_active = 1;
  }
  // ...
}