地方エンジニアの学習日記

興味ある技術の雑なメモだったりを書いてくブログ。たまに日記とガジェット紹介。

gcc mainの前に関数を呼ぶ

gccの拡張を使った小ネタ。ユースケースはあんまり分からないがcソースでmain関数の前に処理を行いたいケースで以下のgccの拡張を使うとできるよって話。

具体的なサンプルは以下

環境

[root@localhost ~]# gcc --version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

ソース

#include <stdio.h>

__attribute__((constructor))
void init_proc()
{
    printf("attr\n");
}

int main(void)
{
    printf("start\n");
    return;
}

init_proc自体はmainからコールしてないので実行されなそうに見えるがattributeを付加しているのでmainより先に実行される。

gsmcustomeffects.hatenablog.com

www.glamenv-septzen.net

共有メモリの生成

共有メモリとはプロセス間通信の中でも割と簡単に行える方法の一つ。SHARED MEMORY

wikipediaより

複数のプログラム間の通信手段として使う場合と、単に複製を用意する冗長さを防ぐ目的の場合などがある。共有メモリはプログラム間でデータをやりとりする効率的手段である。文脈によって、それらプログラムが単一のプロセッサ上で動作する場合と複数の異なるプロセッサ群上で動作する場合がある。単一のプログラムの内部でメモリを使って通信する場合もあり、例えばマルチスレッドが典型的だが、仮想空間をもともと共有している場合は「共有メモリ」とは呼ばない。

共有メモリの操作はsh*って感じのシステムコールが用意されていてこの辺を用いて扱っていく

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
 
int shmget(key_t key, size_t size, int shmflg);
void *shmat(int shmid, void *shmaddr, int shmflg);
int shmdt(void *shmaddr);
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

shmget(2)は共有メモリの領域獲得に成功するとユニークな ID を返しそのIDを元にプロセス間通信を行っていく。

以下のサンプルは親プロセスと子プロセスで異なるメモリ空間を使用しつつメッセージを共有しているサンプル。

mmap(2)の引き数 prot には、メモリ保護をどのように行なうかを指定しています。

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>

void* create_shared_memory(size_t size)
{
  int protection = PROT_READ | PROT_WRITE;
  int visibility = MAP_SHARED | MAP_ANONYMOUS;

  return mmap(NULL, size, protection, visibility, -1, 0);
}

int main(int argc, char ** argv) {
  char* parent_message = "hello";
  char* child_message = "goodbye";

  void* shmem = create_shared_memory(128);

  memcpy(shmem, parent_message, sizeof(parent_message));

  int pid = fork();

  if (pid == 0) {
    printf("Child read: %s", shmem);
    memcpy(shmem, child_message, sizeof(child_message));
    printf("Child wrote: %s", shmem);
  } else {
    printf("Parent read: %s", shmem);
    sleep(1);
    printf("After 1s, parent read: %s", shmem);
  }
}
  • PROT_READ|PROT_WRITE = 読み書き可能 PROT_EXECを追記することで実行可能になる
  • MAP_SHARED | MAP_ANONYMOUS = このマッピングを、このオブジェクトをマップした他の全てのプロセスと共有する。ただしどのファイルとも関連付けされない

goのlspをvim-lspにお引っ越し

vim-lspを使ってgoを便利に使っていく設定方法

vimrc

call plug#begin('~/.vim/plugged')
Plug 'prabirshrestha/async.vim'
Plug 'prabirshrestha/asyncomplete.vim'
Plug 'prabirshrestha/asyncomplete-lsp.vim'
Plug 'prabirshrestha/vim-lsp'
Plug 'mattn/vim-lsp-settings'
Plug 'mattn/vim-goimports'
call plug#end()

plugin setting

nmap <silent> gd :LspDefinition<CR>
nmap <silent> <f2> :LspRename<CR>
nmap <silent> <Leader>d :LspTypeDefinition<CR>
nmap <silent> <Leader>r :LspReferences<CR>
nmap <silent> <Leader>i :LspImplementation<CR>
let g:lsp_diagnostics_enabled = 1
let g:lsp_diagnostics_echo_cursor = 1
let g:asyncomplete_popup_delay = 200
let g:lsp_text_edit_enabled = 0

vim-goからvim-lspへの移行は最近のトレンドなのだろうか記事やらTwitterでもよく見かける気がする。

github.com

vim-go一択だった時代からなぜ変わってしまったのだろうか(最近の肥大化がすごいのは思ってましたが。。)

GitHubActionsで手動実行機能が実装された workflow_dispatch

ついに待望のGitHubActionsにジョブの手動実行が追加されました。🎉

github.blog

ざっくり使い方。

とても簡単でした。

onコンテキストにworkflow_dispatchを追加するだけで手動実行が可能になります。

homecmd/docs.yml at master · ryuichi1208/homecmd · GitHub

上記のように定義しておくだけでActionsタブから手動でジョブを実行させることが可能になります。

パラメータも文字列のみですが渡すことが可能でデフォルト値なんかも設定することができます。

f:id:ryuichi1208:20200715225555p:plain

GUIから簡単なパラメータを渡せるのはとても良い。(凝ったことやるならAPIから叩くの一択なのでそのうち改善されることを期待。)