Chinaunix

标题: FreeBSD10的kern.ipc.maxsockets变成只读了? [打印本页]

作者: lsstarboy    时间: 2014-11-02 20:37
标题: FreeBSD10的kern.ipc.maxsockets变成只读了?
kern.ipc.maxsockets,在9以前是可以通过sysctl和sysctl.conf设置,但是现在却报错了,提示无效的参数,但是默认却有:
# sysctl kern.ipc.maxsockets
kern.ipc.maxsockets: 1046370
# sysctl kern.ipc.maxsockets=1048576
kern.ipc.maxsockets: 1046370
sysctl: kern.ipc.maxsockets=1048576: Invalid argument

作者: lsstarboy    时间: 2014-11-02 20:51
放到loader.conf里面好像起作用,但是显示出来的值是1048580,这个值有什么规则要求吗?
作者: 71v5    时间: 2014-11-15 17:21
目测木有改成只读的,至少我的9.2里面木有,如下:
    77        #define CTLFLAG_RD        0x80000000        /* Allow reads of variable */
    78        #define CTLFLAG_WR        0x40000000        /* Allow writes to the variable */
    79        #define CTLFLAG_RW        (CTLFLAG_RD|CTLFLAG_WR)

   313        SYSCTL_PROC(_kern_ipc, OID_AUTO, maxsockets, CTLTYPE_INT|CTLFLAG_RW,
   314            &maxsockets, 0, sysctl_maxsockets, "IU",
   315            "Maximum number of sockets avaliable");

至于这个值的要求,目测就是新设置的值不能比原来的值小:
root@:~ # sysctl kern.ipc.maxsockets
kern.ipc.maxsockets: 1048576
root@:~ # sysctl kern.ipc.maxsockets=25600
kern.ipc.maxsockets: 1048576
sysctl: kern.ipc.maxsockets=25600: Invalid argument

看下面的处理代码就明白了:
   289        /*
   290         * Sysctl to get and set the maximum global sockets limit.  Notify protocols
   291         * of the change so that they can update their dependent limits as required.
   292         */
   293        static int
   294        sysctl_maxsockets(SYSCTL_HANDLER_ARGS)
   295        {
   296                int error, newmaxsockets;
   297       
   298                newmaxsockets = maxsockets;
   299                error = sysctl_handle_int(oidp, &newmaxsockets, 0, req);
   300                if (error == 0 && req->newptr) {
   301                        if (newmaxsockets > maxsockets) {
   302                                maxsockets = newmaxsockets;
   303                                if (maxsockets > ((maxfiles / 4) * 3)) {
   304                                        maxfiles = (maxsockets * 5) / 4;
   305                                        maxfilesperproc = (maxfiles * 9) / 10;
   306                                }
   307                                EVENTHANDLER_INVOKE(maxsockets_change);
   308                        } else
   309                                error = EINVAL; /* 错误码,Invalid argument */
   310                }
   311                return (error);
   312        }

作者: lsstarboy    时间: 2014-11-16 09:40
回复 4# 71v5


    FreeBSD9是正常的,10.0以后才是这个样子,我查了一下你提到的代码,改为下面的代码了,我没研究过这些结构,你看一下有什么变化?另外我想知道这个值到底是什么规则?
  1. /*
  2. * Sysctl to get and set the maximum global sockets limit.  Notify protocols
  3. * of the change so that they can update their dependent limits as required.
  4. */
  5. static int
  6. sysctl_maxsockets(SYSCTL_HANDLER_ARGS)
  7. {
  8.         int error, newmaxsockets;

  9.         newmaxsockets = maxsockets;
  10.         error = sysctl_handle_int(oidp, &newmaxsockets, 0, req);
  11.         if (error == 0 && req->newptr) {
  12.                 if (newmaxsockets > maxsockets &&
  13.                     newmaxsockets <= maxfiles) {
  14.                         maxsockets = newmaxsockets;
  15.                         EVENTHANDLER_INVOKE(maxsockets_change);
  16.                 } else
  17.                         error = EINVAL;
  18.         }
  19.         return (error);
  20. }
复制代码

作者: lsstarboy    时间: 2014-11-16 09:44
是在sys/kern/uipc_socket.c的代码片断,宏的定义部分好像也没变,难道是个bug、
作者: 71v5    时间: 2014-11-16 17:17
版主,我没装10的系统,从你提供的信息来看,区别如下:
版本9:
   300                if (error == 0 && req->newptr) {
    301                        if (newmaxsockets > maxsockets) {
    302                                maxsockets = newmaxsockets;
    303                                if (maxsockets > ((maxfiles / 4) * 3)) {
    304                                        maxfiles = (maxsockets * 5) / 4;
    305                                        maxfilesperproc = (maxfiles * 9) / 10;
    306                                }
    307                                EVENTHANDLER_INVOKE(maxsockets_change);
    308                        } else
    309                                error = EINVAL; /* 错误码,Invalid argument */


版本10:
12.        if (error == 0 && req->newptr) {
13.                if (newmaxsockets > maxsockets &&
14.                    newmaxsockets <= maxfiles) {
15.                        maxsockets = newmaxsockets;
16.                        EVENTHANDLER_INVOKE(maxsockets_change);
17.                } else
18.                        error = EINVAL;
19.        }

版本9的301行的条件 和 版本10的13行的 条件不一样 版本10还要同时检查newmaxsockets <= maxfiles这个条件:
int        maxfiles;                        /* sys. wide open files limit */

你用sysctl看看你系统上这个值是多少,
作者: 71v5    时间: 2014-11-16 17:29
回头找个时间 把sysctl的具体实现原理跟大家分享一下:wink:
作者: lsstarboy    时间: 2014-11-17 08:46
回复 8# 71v5
  1. # sysctl kern.maxfiles kern.ipc.maxsockets
  2. kern.maxfiles: 204800
  3. kern.ipc.maxsockets: 1046300

  4. # sysctl kern.ipc.maxsockets=1048576
  5. kern.ipc.maxsockets: 1046300
  6. sysctl: kern.ipc.maxsockets=1048576: Invalid argument

  7. # sysctl kern.ipc.maxsockets=204000
  8. kern.ipc.maxsockets: 1046300
  9. sysctl: kern.ipc.maxsockets=204000: Invalid argument

复制代码
“Invalid argument”这个是哪一句报出来的?是sysctl_handle_int返回的,还是EINVAL?看宏的名称,应该是EINVAL,如果是这样,则说明newmaxsockets > maxsockets不满足,然后……我就不懂了,newmaxsockets在sysctl_handle_int里被改变了?
作者: 71v5    时间: 2014-11-17 23:10
本帖最后由 71v5 于 2014-11-18 00:30 编辑

版主,我搞错了哈,大概如下:

系统范围内的限制:
  1. int        maxfiles;        /* sys. wide open files limit,打开文件数目的限制 */
复制代码
从下面的宏可以知道:
  1. SYSCTL_PROC(_kern_ipc, OID_AUTO, maxsockets, CTLTYPE_INT|CTLFLAG_RW,&maxsockets, 0, sysctl_maxsockets, "IU", "Maximum number of sockets avaliable");
复制代码
maxsockets->"Maximum number of sockets avaliable",sysctl对该变量的修改最终都是通过函数sysctl_maxsockets来操作。

宏SYSCTL_PROC的简单原理就是构造一个struct sysctl_oid类型的对象来描述maxsockets,并将该对象的地址保存到特定的section中,在内核初始化的过程中,会遍历该
section,使用保存的struct sysctl_oid类型的对象构建一棵MIB TREE。

[函数sysctl_maxsockets简单描述如下]:
  1.         /*
  2.          * 宏SYSCTL_HANDLER_ARGS展开如下:
  3.          * struct sysctl_oid *oidp, void *arg1,intptr_t arg2, struct sysctl_req *req
  4.          *
  5.          * 在这里暂时只需要关心第一个和第四个参数:
  6.          * oidp:内核中用来描述maxsockets的struct sysctl_oid对象。
  7.          * req:用户态的sysctl命令是通过sysctl*系统调用调用实现的,struct sysctl_req
  8.          * 类型的对象将传递进来的参数封装起来。
  9.          */
  10.    287        static int
  11.    288        sysctl_maxsockets(SYSCTL_HANDLER_ARGS)
  12.    289        {
  13.    290                int error, newmaxsockets;
  14.    291                /*
  15.                  * 292:newmaxsockets保存了之前maxsockets的值。
  16.                  *
  17.                  * 293:函数sysctl_handle_int执行完后:
  18.                  *      newmaxsockets:被修改为新设置的value。
  19.                  *      maxsockets:没有被修改,保持原来的value。
  20.                  * 暂时不用关心294行if语句的条件,这里假设其为真。
  21.                  * 295-300之间的语句:
  22.                  * 新设置的maxsockets的值要大于之前maxsockets的值并且
  23.                  * 新设置的maxsockets的值要<= maxfiles。
  24.                  * 当上面的条件都满足时,此时才更新maxsockets。
  25.                  *
  26.                  * 还可以看出,当要更新maxsockets时,先要看看maxfiles的值,根据需要
  27.                  * 先调整maxfiles的值,然后再更新maxsockets。
  28.                  *
  29.                  * EINVAL:是一个error number,这是内核返回给调用者(一般是函数库中的函数),
  30.                  *         的错误码,由调用者将其转换为相应的错误描述字符串,比如错误码
  31.                  *         EINVAL的错误描述就是“Invalid argument”。
  32.                  *         其实更准确的应该是,kernel中的函数将错误码返回给调用者(一般是函数库中的函数),
  33.                  *         调用者将这个error number保存到全局变量errno,一般情况下,将给应用程序返回
  34.                  *         -1,应用程序检查返回值如果是-1,就标识出错,此时就回去检查errno。
  35.                  */
  36.    292                newmaxsockets = maxsockets;
  37.    293                error = sysctl_handle_int(oidp, &newmaxsockets, 0, req);
  38.    294                if (error == 0 && req->newptr) {
  39.    295                        if (newmaxsockets > maxsockets &&
  40.    296                            newmaxsockets <= maxfiles) {
  41.    297                                maxsockets = newmaxsockets;
  42.    298                                EVENTHANDLER_INVOKE(maxsockets_change);
  43.    299                        } else
  44.    300                                error = EINVAL;
  45.    301                }
  46.    302                return (error);
  47.    303        }
复制代码

作者: 71v5    时间: 2014-11-17 23:20
版主 貌似还有点问题 我再看看
作者: 71v5    时间: 2014-11-17 23:36
版主,已经更新了,我测试了一下,但更新成功时,系统将新设置的值调整了,这块我暂时不明白是什么原因造成的。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2