FreeBSD没有free命令,但是提供了一个freecolor命令,用来查看还有多少可用的内存。Freecolor官网在这里,其代码逻辑比较简单。如果系统提供/proc/meminfo,就直接从这个虚拟文件系统获取信息,否则就透过libstatgrab这个第三方库。因为FreeBSD默认不会挂载/proc文件系统,所以会使用libstatgrab

Libstatgrab获得FreeBSD系统内存使用状况的代码:

#elif defined(FREEBSD) || defined(DFBSD)
    /*returns pages*/
    size = sizeof(total_count);
    if (sysctlbyname("vm.stats.vm.v_page_count", &total_count, &size, NULL, 0) < 0) {
        RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_page_count");
    }

    /*returns pages*/
    size = sizeof(free_count);
    if (sysctlbyname("vm.stats.vm.v_free_count", &free_count, &size, NULL, 0) < 0) {
        RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_free_count");
    }

    size = sizeof(inactive_count);
    if (sysctlbyname("vm.stats.vm.v_inactive_count", &inactive_count , &size, NULL, 0) < 0) {
        RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_inactive_count");
    }

    size = sizeof(cache_count);
    if (sysctlbyname("vm.stats.vm.v_cache_count", &cache_count, &size, NULL, 0) < 0) {
        RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_cache_count");
    }

    /* Of couse nothing is ever that simple :) And I have inactive pages to
     * deal with too. So I'm going to add them to free memory :)
     */
    mem_stats_buf->cache = (size_t)cache_count;
    mem_stats_buf->cache *= (size_t)sys_page_size;
    mem_stats_buf->total = (size_t)total_count;
    mem_stats_buf->total *= (size_t)sys_page_size;
    mem_stats_buf->free = (size_t)free_count + inactive_count + cache_count;
    mem_stats_buf->free *= (size_t)sys_page_size;
    mem_stats_buf->used = mem_stats_buf->total - mem_stats_buf->free;
#elif defined(WIN32)

可以看到,所有free_countinactive_countcache_count都算作free,即可用的内存。

而获得swap使用率则通过kvm接口:

#elif defined(ALLBSD)
    /* XXX probably not mt-safe! */
    kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, NULL);
    if(kvmd == NULL) {
        RETURN_WITH_SET_ERROR("swap", SG_ERROR_KVM_OPENFILES, NULL);
    }

    if ((kvm_getswapinfo(kvmd, &swapinfo, 1,0)) == -1) {
        kvm_close( kvmd );
        RETURN_WITH_SET_ERROR("swap", SG_ERROR_KVM_GETSWAPINFO, NULL);
    }

    swap_stats_buf->total = (long long)swapinfo.ksw_total;
    swap_stats_buf->used = (long long)swapinfo.ksw_used;
    kvm_close( kvmd );

    swap_stats_buf->total *= sys_page_size;
    swap_stats_buf->used *= sys_page_size;
    swap_stats_buf->free = swap_stats_buf->total - swap_stats_buf->used;
#elif defined(WIN32)