阅读视图

发现新文章,点击刷新页面。

搬家

最近连续加了一个月班,所以上次雄心勃勃制定的更新计划又鸽了

另一件事是租了个主卧,从公司宿舍里搬出来了

麒麟系统编译jcef

获取系统

可以从优麒麟的官网获取最新版22.04、20.04和V10的安装包,我这里用的是一个老版本。
https://www.ubuntukylin.com/downloads/
麒麟官网

安装过程这里就省略了,基本上按照提示来就行了。

下载JCEF代码

jcef项目在Bitbucket上,地址如下:
https://bitbucket.org/chromiumembedded/java-cef/src/master/
现在jcef在Github也有代码了,但是提issue的话最好是去Bitbucket上:
https://github.com/chromiumembedded/java-cef

sudo apt-get install git #麒麟系统有的版本并没有git需要先手动安装一下

git clone https://github.com/chromiumembedded/java-cef.git #下载源代码

编译JCEF

其实打开代码里的CMakeLists.txt可以看到编译的要求和基本的步骤,可以看到最新版的jcef100要求的CMake的最低版本是3.19,但是目前麒麟系统能下载到的最新版为3.5.1,不符合要求。这里的话有两种方法,一种是下载最新版CMake源码编译安装,另一种是编译一个老版本的jcef。

我选的是后一种方法,毕竟,用麒麟系统的人也不是那么需要最新版的代码

查看git log可以发现,在2021年12月14日,jcef更新了MakeFile,而在此之前的jcef95要求的CMake版本是2.8。
使用git reset退回到CEF version 95.7.14+g9f72f35+chromium-95.0.4638.69这个版本。

git reset --hard ae6912a705e6a2a60f0f156fcc2e8c03bf8285c4

我们还需要安装build-essential这个包。

sudo apt-get install build-essential

麒麟系统自带了JDK 1.8,但是并没配置Java Home,需要我们手动配置一下

vi /etc/profile

#在末尾添加

export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH

#保存退出

#退出以后执行 
source /etc/profile

然后就可以开始编译了:

cd /java-cef/src  #到代码路径下src文件夹下
mkdir jcef_build && cd jcef_build

cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug ..
make -j4

如果你的网络条件比较好的话,基本就可以顺利编译完成,但是如果不那么理想的话,可以手动去http://opensource.spotify.com/cefbuilds/下载一下编译所需要的文件,需要下载的是95版本Linux 64的包。将下载好的包放到java-cef/src/third_party/cef路径下。

使用如下指令编译所需的Java Class文件。

cd /java-cef/src/tools
./compile.sh linux64

测试编译结果

cd /java-cef/src/tools
./run.sh linux64 Debug detailed

运行效果如图
jcef test

打包

测试正常后可以使用打包工具进行打包,毕竟不可能每台机器都这样编译一通。

cd /java-cef/src/tools
./make_distrib.sh linux64

打包的文件在/out路径下。

最后

其实,官方也知道jcef这个编译是个大坑,没个半天功夫根本搞不定,于是官方把jcef运行需要的包和可执行文件上传到了Maven,方便了太多。但是这个可执行文件在Windows下测试可行,而麒麟系统下却报错,有点可惜。
Windows下的maven dependency:

    <dependency>
        <groupId>me.friwi</groupId>
        <artifactId>jcefmaven</artifactId>
        <version>95.7.14.11</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/me.friwi/jcef-natives-windows-amd64 -->
    <dependency>
        <groupId>me.friwi</groupId>
        <artifactId>jcef-natives-windows-amd64</artifactId>
        <version>jcef-544024e+cef-95.7.14+g9f72f35+chromium-95.0.4638.69</version>
    </dependency>

顺便提一嘴,这个native包用阿里的源下载不下来,后来适用华为的源下下来的。

Linux IO多路复用分析(Select、Poll和Epoll)

前段时间被迫把一坨没人维护代码中的Select机制换成了Epoll,借此机会梳理一下Select、Poll和Epoll的原理。

I/O多路复用:

I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。

Select:

函数原型和使用:

#include <sys/select.h>
#include <sys/time.h>

int select(int maxfdp1,fd_set *readset,fd_set *writeset,fd_set *exceptset,const struct timeval *timeout)

void FD_ZERO(fd_set *fdset);//清空集合
void FD_SET(int fd, fd_set *fdset);//将一个给定的文件描述符加入集合之中
void FD_CLR(int fd, fd_set *fdset);//将一个给定的文件描述符从集合中删除
int FD_ISSET(int fd, fd_set *fdset);// 检查集合中指定的文件描述符是否可以读写 

缺点:

  1. 每次调用select,都需要把fd集合从用户态拷贝到内核态,也需要在内核遍历传递进来的所有fd,开销过大
  2. select支持的文件描述符数量过小,默认是1024,且调大需要重新编译系统内核

Poll:

函数原型和使用:

# include <poll.h>

int poll ( struct pollfd * fds, unsigned int nfds, int timeout);

/*Poll结构体*/
struct pollfd {
int fd;/* 文件描述符 */
short events;/* 等待的事件 */
short revents;/* 实际发生了的事件 */
};

缺点:

  • 只解决了select描述符上限的问题,没解决效率问题。

Epoll:

epoll是在2.6内核中提出的,是之前的select和poll的增强版本。相对于select和poll来说,epoll更加灵活,没有描述符限制。epoll使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的copy只需一次。

函数原型和使用:

#include <sys/epoll.h>

int epoll_create(int size);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);

struct epoll_event {
  __uint32_t events;  /* Epoll events */
  epoll_data_t data;  /* User data variable */
};

缺点:

  • 使用较为复杂

简单的总结:

对比 Select Poll Epoll
机制 轮询 轮询 通知
默认FD上限 1024 无上限 无上限
效率

参考资料:

https://www.cnblogs.com/anker/p/3265058.html
https://blog.csdn.net/qq_39612543/article/details/121963681

居家的五一

今年五一还挺特别,调休调出五天假结果不能回家,然后有不能去景区玩,后来又进一步变成了不能堂食。只好窝在家里研究厨艺
不得不说,程序员各个都是人才,连《程序员做饭指南》都出了,不再有少许等模糊的词,真是讲究。
howtocook

换了个主题

又换了个主题,其实就是官方的2012自己魔改了一下。

主要的改动

  1. 改为单栏主题
  2. 扩大文字部分宽度,更适应宽屏显示效果
  3. 更换部分字体
  4. 借助插件改为markdown

主题后续计划:

  1. 归档页
  2. 悬浮目录
  3. 返回顶部

博客后续计划:

  • 把一部分以前写的中二文章隐藏
  • 后续主要写一下生活、旅游和一丢丢技术文章
  • 争取每月至少更新一篇
  • 做一个special的网页记录生活

争取不打脸:stuck_out_tongue_winking_eye:

Java使用JNA访问本地库

JNA(Java Native Access )是一个基于JNI的开源库,能有效提高Java访问调用本地库的效率。

官方介绍

JNA 为 Java 程序提供了对本机共享库的轻松访问,而无需编写除 Java 代码之外的任何内容 - 不需要 JNI 或本机代码。此功能可与Windows的Platform /Invoke和Python的ctype相媲美。

JNA 允许您使用自然 Java 方法调用直接调用本机函数。Java 调用看起来就像本机代码中的调用一样。大多数呼叫不需要特殊处理或配置;不需要样板或生成的代码。

JNA 使用一个小型 JNI 库存根来动态调用本机代码。开发人员使用 Java 接口来描述目标本机库中的函数和结构。这使得利用本机平台功能变得非常容易,而不会产生为多个平台配置和构建 JNI 代码的高开销。阅读此更深入的描述。

使用方法

import com.sun.jna.Library;
import com.sun.jna.Native;
public interface JnaDemo extends Library {
    JnaDemo INSTANCE = (JnaDemo) Native.loadLibrary("demo",JnaDemo.class);
    //demo处写需要调用的动态库名字,不写.so或.dll
    ...
    //此处写需要调用的库函数,注意不同类型的对应关系
}

注意事项:

  • 如果同时加载多个动态库,不要出现同名的函数,否则可能会出现致命错误。
  • C++与Java类型的对应关系一定要写对,否则也会出现致命错误。

待续

你好,2021

瞬间就到了2021,疫情导致2020黑天鹅频发,对我的想法也有了很大的影响。

以前觉得毕业了要去互联网公司,结果最后找个了央企的工作。

以前觉得户口啥的有什么重要的,结果最后为了稳拿户口放弃了好几个机会。

强行北漂会遇到什么事,也只有之后慢慢体验。


2020最重要的事还是遇到了她。

待更新

❌