关于vsftpd源代码的一些疑问

1. 写数据的时候为什么要把两边的页保护起来?

 p_mmap = vsf_sysutil_map_anon_pages(round_up); // 这里面调用的是mmap 什么时候unmap?

  /* Map the first and last page inaccessible */

  p_no_access_page = p_mmap + round_up - page_size;

  vsf_sysutil_memprotect(p_no_access_page, page_size, kVSFSysUtilMapProtNone);

  /* Before we make the "before" page inaccessible, store the size in it.

   * A little hack so that we don't need to explicitly be passed the size

   * when freeing an existing secure buffer

   */

  *((unsigned int*)p_mmap) = round_up;

  p_no_access_page = p_mmap;

  vsf_sysutil_memprotect(p_no_access_page, page_size, kVSFSysUtilMapProtNone);// 里面调到了mprotect(),参考:Linux中mprotect()函数的用法-CSDN博客

一大片内存中,两边的页不让访问。

2. 一个请求结束的时候怎么处理的?

void vsf_cmdio_write_exit(struct vsf_session* p_sess, int status, const char* p_text,

                     int exit_val)

{

  /* Unblock any readers on the dying control channel. This is needed for SSL

   * connections, where the SSL control channel slave is in a separate

   * process.

   */

  vsf_sysutil_activate_noblock(VSFTP_COMMAND_FD);

  vsf_sysutil_shutdown_read_failok(VSFTP_COMMAND_FD);

  vsf_cmdio_write(p_sess, status, p_text);

  vsf_sysutil_shutdown_failok(VSFTP_COMMAND_FD);

  vsf_sysutil_exit(exit_val);

}

3. 各种信号处理

子进程创建之前注册信号:

void vsf_two_process_start(struct vsf_session* p_sess)

{

  vsf_sysutil_install_sighandler(kVSFSysUtilSigTERM, handle_sigterm, 0, 1); -----注册SIGTERM信号的处理函数,为什么在这里注册?可以尽早捕获这个消息

  /* Overrides the SIGKILL setting set by the standalone listener. */

  vsf_set_term_if_parent_dies();

  /* Create the comms channel between privileged parent and no-priv child */

  priv_sock_init(p_sess);

  ......

  vsf_sysutil_install_sighandler(kVSFSysUtilSigCHLD, handle_sigchld, 0, 1);//这是处理SIGCHLD消息的处理函数。放在这里是因为后面需要创建子进程,子进程一创建就可能会发SIGCHLD消息。必须要在之前注册。

.......

}

handle_sigchld函数中会调用wait或者waitpid 函数来等待子进程结束。

关于vsf_set_term_if_parent_dies();函数

void vsf_set_term_if_parent_dies()
{
#ifdef VSF_SYSDEP_HAVE_SETPDEATHSIG
  if (prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0) != 0) 
  {
    die("prctl");
  }
#endif
}

prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0) 这个函数的目的是,在得知他的父进程退出时,把父进程的退出信号设置成SIGTERM。很强大把?prctl这个函数还有很多功能,可以查询一下。

子进程创建之前先阻塞SIGCHILD信号,等把必要的动作做完之后再重新注册SIGCHILD信号,也是为了防止产生僵尸进程。

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); //----相当于把SigCHLD信号阻塞,就是暂时不处理子进程状态的变化。等下面的动作完了,再来响应SigCHLD消息
  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;
  }
  /* Handle loading per-user config options */
  handle_per_user_config(p_user_str);
  /* Set this before we fork */
  p_sess->is_anonymous = anon;
  priv_sock_close(p_sess);
  priv_sock_init(p_sess);
  vsf_sysutil_install_sighandler(kVSFSysUtilSigCHLD, handle_sigchld, 0, 1);//----重新注册SigCHLD信号
  .......

  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值