如何在Go中使用POSIX命名信号量

go 本身提供的 semaphore 只能在同一个进程多个协程或线程间使用,无法在不同的 go 进程之间使用,所以本文介绍,如何使用 go 中的 syscall 来使用 POSIX 系统提供的命名信号量。 Go 中的系统调用 在 go 中,系统调用是通过 syscall 包提供的 Syscall 函数来进行系统调用的,不同的系统调用有不同的 trap,以及不同长度的参数。 trap go 在 syscall 包中定义了大量的系统调用码,具体定义在文件1.20.6/go/src/syscall/zsysnum_darwin_arm64.go 。不同操作系统上,定义所使用的文件是不同的,这些定义都是通过不同系统的c 语言头文件自动生成的。比如 linux amd64 操作系统的定义在1.20.6/go/src/syscall/zerrors_linux_amd64.go。 不同长度的参数 syscall 包有 Syscall、Syscall6 两个函数,对应于不同的操作系统调用参数长度的情况。 Syscall 总共接收 4 个参数,第一个是 trap 定义,描述具体的系统调用,剩下的 3 个是系统调用所需的参数。 Syscall6 总共接收 7 个参数,第一个是 trap 定义,描述具体的系统调用,剩下的 6 个是系统调用所需的参数。 如果使用 Syscall 或 Syscall6 时,系统调用所需的参数不满足函数形参所需的数量,则剩下的参数传0。 例如,在 POSIX 系统上打开一个命名信号量的系统调用是: 1 sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value); 因为系统调用的参数有 4 个,而 Syscall 接收的全部形参才 4 个,所以 Syscall 不能满足我们的需求,只能使用 Syscall6 这个函数。而 Syscall6 总共需要 7 个形参,其中有 6 个是系统调用参数,我们只有 4 个系统调用参数,那么剩下的 2 个系统调用参数,我们就可以使用 0 替代,例如: ...

2024-09-01 · 3 分钟

Python源码笔记——Python中的列表对象

1.列表结构体 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 #define PyObject_VAR_HEAD PyVarObject ob_base; typedef struct { PyObject ob_base; Py_ssize_t ob_size; /* Number of items in variable part */ } PyVarObject; typedef struct { PyObject_VAR_HEAD /* Vector of pointers to list elements. list[0] is ob_item[0], etc. */ PyObject **ob_item; /* ob_item contains space for 'allocated' elements. The number * currently in use is ob_size. * Invariants: * 0 <= ob_size <= allocated * len(list) == ob_size * ob_item == NULL implies ob_size == allocated == 0 * list.sort() temporarily sets allocated to -1 to detect mutations. * * Items must normally not be NULL, except during construction when * the list is not yet visible outside the function that builds it. */ Py_ssize_t allocated; } PyListObject; ob_item是指向列表元素的指针向量,当我们通过list[0]获取元素时,实际上是获取的ob_item[0]的元素。ob_item的类型是PyObject*,由此我们可以知道,为什么Python中的list能存储任意对象的数据,这是因为任何Python对象都可以强转为PyObject*的指针类型。 ...

2023-04-07 · 6 分钟

Python源码笔记——Python中的字符串对象

1.字符串对象 在Python3.11.2中,字符串类型PyUnicodeObject的实现相当的复杂 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 typedef struct { PyObject_HEAD Py_ssize_t length; /* Number of code points in the string */ Py_hash_t hash; /* Hash value; -1 if not set */ struct { ... } state; wchar_t *wstr; /* wchar_t representation (null-terminated) */ } PyASCIIObject; typedef struct { PyASCIIObject _base; Py_ssize_t utf8_length; /* Number of bytes in utf8, excluding the * terminating \0. */ char *utf8; /* UTF-8 representation (null-terminated) */ Py_ssize_t wstr_length; /* Number of code points in wstr, possible * surrogates count as two code points. */ } PyCompactUnicodeObject; typedef struct { PyCompactUnicodeObject _base; union { void *any; Py_UCS1 *latin1; Py_UCS2 *ucs2; Py_UCS4 *ucs4; } data; /* Canonical, smallest-form Unicode buffer */ } PyUnicodeObject; 类型对象 ...

2023-04-07 · 4 分钟

Python源码笔记——Python中的整数对象

1.整数对象 在Python3.11.2中,整数结构体叫做PyLongObject。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #if PYLONG_BITS_IN_DIGIT == 30 typedef uint32_t digit; ... #elif PYLONG_BITS_IN_DIGIT == 15 typedef unsigned short digit; ... #else #error "PYLONG_BITS_IN_DIGIT should be 15 or 30" #endif typedef struct _longobject { /* PyObject ob_base; Py_ssize_t ob_size; */ PyObject_VAR_HEAD digit ob_digit[1]; } PyLongObject; 通过PyObject_VAR_HEAD我们可以确定,在新版Python中,整形是一个不定长对象。 通过前面的文章,我们知道,对于Python中的对象,与对象相关的元信息实际上都保存在与对象对应的类型对象中,对于PyLongObject,这个类型对象是PyLong_Type。 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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 PyTypeObject PyLong_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "int", /* tp_name */ offsetof(PyLongObject, ob_digit), /* tp_basicsize */ sizeof(digit), /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ long_to_decimal_string, /* tp_repr */ &long_as_number, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc)long_hash, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_LONG_SUBCLASS | _Py_TPFLAGS_MATCH_SELF, /* tp_flags */ long_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ long_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ long_methods, /* tp_methods */ 0, /* tp_members */ long_getset, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ long_new, /* tp_new */ PyObject_Free, /* tp_free */ }; PyLongObject对象的各种操作(比较、运算等)实际上就是调用PyLong_Type中的tp_as_number这个结构体中定义的各种函数指针。 ...

2023-04-07 · 5 分钟

Python源码笔记——Python对象机制的基石【PyObject】

所有源码均基于Python 3.11.2 1.PyObject定义 1 2 3 4 5 6 7 8 // 实际上没有任何东西被声明为PyObject,但是每个指向Python对象的指针都可以转换为PyObject*。 // 这是手动模拟的继承。同样的,每个指向可变大小的Python对象的指针也可以转换为PyObject*,此外,也可以转换为PyVarObject*。 typedef struct _object { _PyObject_HEAD_EXTRA // 定义指针以支持所有活动堆对象的双向链表refchain Py_ssize_t ob_refcnt; PyTypeObject *ob_type; } PyObject; Python通过ob_refcnt字段实现基于引用计数的垃圾回收机制。对于某一个对象A,当有一个新的PyObject*引用A对象时,A的引用计数会增加1,当这个PyObject*引用被删除时,A的引用计数应当减1,当此字段为0时,进行垃圾回收(不一定会释放内存空间,Python中还有缓存机制)。 _PyObject_HEAD_EXTRA是一个宏,当编译Python时指定参数--with-trace-refs,那么Py_TRACE_REFS 会被定义。 1 2 3 4 5 6 7 8 9 10 11 12 #ifdef Py_TRACE_REFS /* Define pointers to support a doubly-linked list of all live heap objects. */ #define _PyObject_HEAD_EXTRA \ PyObject *_ob_next; \ PyObject *_ob_prev; #define _PyObject_EXTRA_INIT _Py_NULL, _Py_NULL, #else # define _PyObject_HEAD_EXTRA # define _PyObject_EXTRA_INIT #endif ob_type是一个结构体,对应着Python内部的一种特殊的对象,用来指定一个对象类型的类型对象。 ...

2023-04-07 · 2 分钟

Mosh连接服务器时终端颜色显示问题

在使用mosh连接到服务器Ubuntu 20.04时,发现终端(终端是Kitty,支持256color)的颜色不能正常显示。 使用命令查看了一下$TERM的设置 1 2 $ echo $TERM xterm-256color 显示的是xterm-256color,说明配置的是没问题的。 查看mosh的版本: 1 2 $ mosh --version 1.3.2 可以看到mosh的版本是1.3.2,这个版本的发布日期是2017-07-22,但是github上master分支一直在开发中。 想着时间已经过去这么久了,官方应该已经解决了这个问题,毕竟现在的很多终端都是支持256color的,所以就在issue中搜索了一下,真的找到了一个解决方案。 定位问题 在2017年11月23号就有人提过关于mosh的256color显示支持问题,而官方也已经解决了这个问题,但是不知道为什么都已经过去这么久了还没有发布新的版本。 具体的issue。不过评论中说的PPA也已经很久没有更新了。所以我们需要新的方案解决Linux系统的问题。 解决方案 想要让mosh能正确的显示256color,就只能手动编译mosh的master分支。 可以查看官方的安装教程,包含手动编译的教程。 记得先将之前的安装卸载掉。 Mac 在MacOS平台上,可以使用brew来进行自动的编译和安装。 1 2 $ brew uninstall mosh $ brew install --HEAD mosh Mac在编译安装的时候,会提示更新或者安装xcode命令行工具,就按照brew执行过程中的提示操作即可。 Linux 在Ubuntu 20.04上安装,需要手动克隆mosh的仓库 在安装之前中,需要安装依赖,Ubuntu最新版本的依赖,比较少。如果你是比较旧的版本,可以参考官方的编译教程,里面有详细的依赖。 1 $ sudo apt install libncurses5-dev protobuf-compiler 1 2 3 4 5 6 $ git clone https://github.com/mobile-shell/mosh.git $ cd mosh $ ./autogen.sh $ ./configure $ make $ sudo make install 最后执行make install的时候,最好添加sudo,因为涉及到将编译生成的可执行文件复制到系统可查找到的bin目录下。 ...

2019-06-01 · 1 分钟

关于Go Modules的一些内容

启用Go Modules go mod在Go >= 1.13才默认启用,在Go >= 1.11已经开始支持了go mod。 设置环境变量 1 2 3 4 5 6 7 8 9 # 启用go module export GO111MODULE=on # 设置GOPATH,开启go mod之后,这个目录主要用来存放依赖包 export GOPATH=~/go_modules # 设置go代理,在运行go test/build等时会自动下载依赖 # 使用go get下载依赖需要在GOPATH中执行才会使用代理 export GOPROXY=https://goproxy.io go mod使用 在$GOPATH/src之外的任意目录创建一个目录, 1 2 mkdir -p /home/gopher/project cd /home/gopher/project 这个目录就是你项目的根目录,在目录中创建mod管理文件 1 go mod init project 如果你这个项目是放在github上的,那么在创建文件的时候可以这样写,project为你github项目名称 1 go mod init github.com/YourName/project go.mod的初始内容cat go.mod为: 1 2 3 module project go 1.12 go.mod只需要在项目的根目录创建一次即可,在项目中Go会自动查找当前目录的全部父级目录,直到找到go.mod。 ...

2019-06-01 · 1 分钟

Jenkins处理GitLab Hook

jenkins安装Generic Webhook Trigger Plugin插件 {% asset_img Generic_Webhook_Trgger.png Generic\ Webhook\ Trgger具体配置 %} 创建任务,在构建触发器中勾选Generic Webhook Trigger, 在展开的页面中会有一个URL, 这个URL是配置Webhook使用的,一般形式是http://JENKINS_URL/generic-webhook-trigger/invoke, JENKINS_URL是初始配置jenkins时会有的,一般是http://IP:8080的形式。 如果之前有配置过GitLab webhook, 请去除这个,不然Generic Webhook Trigger不会生效。 如果Git仓库的验证使用的是用户名和密码,那么就不需要配置Token. 复制这个URL,将JENKINS_URL替换为自己的真实数据,在GitLab的对应的项目的设置-->集成中输入,没有安全令牌,勾选自己需要的触发器事件,SSL证书验证可以开启,也可以不开启,推荐开启。 任务设置界面还有Post content parameters, Header parameters, Request parameters, 分别是请求的post数据,header头,请求头。 一般我们只需要post的数据里的内容就够了。 图片的3,4分别是变量名(3),值(4)。值是直接从post的json格式的数据中取出来的,注意,值的获取方式是JSONPath,并且里面有点,如果json数据有多层,那么就多点几次,比如$.project.name等,可以配置多个变量组。 我们还可以Generic Webhook Trigger配置Optional filter,设置一个触发事件,比如只有当你推送的分支是develop的时候,才去构建。 在Optional filter的Expression框中输入^(refs/heads/develop)$, 在下面的Text框中输入步骤3的变量名,这里写$ref。 在shell中使用变量名的方式也是直接使用,例如echo $ref, 注意没有点。 配置完成后,保存,可以点击刚刚配置的GitLab的webhook页面的Test对应的事件测试。 GitLab的push的hook数据: 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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 { "object_kind": "push", "before": "95790bf891e76fee5e1747ab589903a6a1f80f22", "after": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "ref": "refs/heads/master", "checkout_sha": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "user_id": 4, "user_name": "John Smith", "user_username": "jsmith", "user_email": "john@example.com", "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80", "project_id": 15, "project":{ "id": 15, "name":"Diaspora", "description":"", "web_url":"http://example.com/mike/diaspora", "avatar_url":null, "git_ssh_url":"git@example.com:mike/diaspora.git", "git_http_url":"http://example.com/mike/diaspora.git", "namespace":"Mike", "visibility_level":0, "path_with_namespace":"mike/diaspora", "default_branch":"master", "homepage":"http://example.com/mike/diaspora", "url":"git@example.com:mike/diaspora.git", "ssh_url":"git@example.com:mike/diaspora.git", "http_url":"http://example.com/mike/diaspora.git" }, "repository":{ "name": "Diaspora", "url": "git@example.com:mike/diaspora.git", "description": "", "homepage": "http://example.com/mike/diaspora", "git_http_url":"http://example.com/mike/diaspora.git", "git_ssh_url":"git@example.com:mike/diaspora.git", "visibility_level":0 }, "commits": [ { "id": "b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327", "message": "Update Catalan translation to e38cb41.", "timestamp": "2011-12-12T14:27:31+02:00", "url": "http://example.com/mike/diaspora/commit/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327", "author": { "name": "Jordi Mallach", "email": "jordi@softcatala.org" }, "added": ["CHANGELOG"], "modified": ["app/controller/application.rb"], "removed": [] }, { "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "message": "fixed readme", "timestamp": "2012-01-03T23:36:29+02:00", "url": "http://example.com/mike/diaspora/commit/da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "author": { "name": "GitLab dev user", "email": "gitlabdev@dv6700.(none)" }, "added": ["CHANGELOG"], "modified": ["app/controller/application.rb"], "removed": [] } ], "total_commits_count": 4 }

2019-06-01 · 2 分钟

Jenkins与RocketChat集成

Jenkins与RocketChat集成 在Jenkins中安装插件RocketChat Notifier 配置信息 点击Jenkins左侧的系统管理-->系统设置, 找到Global RocketChat Notifier Settings. 配置Rocket Server URL, 是URL:PORT的类型, 例: http://chat.xxxx.com:80. 配置Login Username和Login password, 是RocketChat的账号密码. Channel, 发送的频道. Build Server URL, 构建的服务器和端口, http://192.168.0.1:8080 点击Test Connection, Success表示配置成功.

2019-06-01 · 1 分钟

Jenkins+Python+GitLab持续集成

创建任务 登录Jenkins,点击左侧列表的新建选项。输入任务名称,选择构建一个自由风格的软件项目,点击确定。 配置 在任务配置界面,可以设置General标签中的丢弃旧的构建选项,设置保持构建的天数和保持构建的最大个数。 点击源码管理标签,选择git,在Repository URL中输入Git仓库的链接。 如果是HTTP链接,选择Credentials一行的Add > Jenkins,在Kind一行下拉选择Username with password,在下方Username和Password框中输入用户名和密码。 使用docker jenkins容器里面的ssh-key。 直接使用服务器的ssh key就可以了。如果指定Path to key需要使用docker中的ssh key。如果使用Source files那么需要使用docker容器中的key, 因为Source files的相对路径不是固化到本地的路径, 而是docker中的路径. 如果是SSH链接,选择SSH Username with private key,在Username框中输入用户名,Private Key 选择为Enter directly,在显示的key框中输入私钥。(生成秘钥ssh-keygen -t rsa -C "email.com",生成的文件在home目录下的.ssh目录下,使用命令cat id_rsa查看私钥,复制到key框中)。点击最下方的Add按钮,保存设置。 在Credentials的下拉选项中选择刚刚创建Username。 使用定时任务 在构建触发器标签里选择Poll SCM,输入H/2 * * * *, 最后点击保存。 这是一个定时任务,每隔2分钟查询一次代码,如果有更新,就执行任务。 使用webhook 使用webhook比定时任务更好,webhook只有在push或指定操作时,jenkins会拉取代码,不用定时访问,耗费资源。 需要安装的插件Gitlab Hook、GitLab、Gitlab Authentication、Build Authorization Token Root 配置job,在构建触发器中勾选Build when a change is pushed to GitLab. GitLab CI Service URL: http://服务器IP:8080/project/demo ,URL后面是回调地址,再点击高级,再Secret token行,点击Generate生成token。 在GitLab服务器上的相对应的项目的Settings里面的Integrations中,配置webhook,输入在jenkins中获取的URL,和token,可以根据需要勾选事件,开启SSL,点击Add webhook。会在Add webhook按钮下生成一个webhook,点击test,会弹出勾选的事件,选择相应的事件,会在页顶弹出Hook executed successfully: HTTP 200,到此,webhook配置完成。 ...

2019-06-01 · 2 分钟