init.dを使用して非リアルタイムスレッドでリアルタイムpthreadを作成する

init.dを使用して非リアルタイムスレッドでリアルタイムpthreadを作成する

Linux端末で実行すると正しく実行されるC ++コードがありますが、SystemV(init.d)スクリプトで実行するとEPERMエラーが発生します。始めに。エラーは、生成するスレッドに次の属性が割り当てられているpthread_createで発生します。

pthread_t reading_thread;

pthread_attr_t read_attr;
struct sched_param read_param; 
pthread_attr_init(&read_attr);
pthread_attr_setschedpolicy(&read_attr, SCHED_FIFO);
pthread_attr_setinheritsched(&read_attr, PTHREAD_EXPLICIT_SCHED);
read_param.sched_priority = 30;
pthread_attr_setschedparam(&read_attr, &read_param);

k = pthread_create(&reading_thread, &read_attr, Reading_Thread_Function, 
            (void*) &variable_to_pass_to_Reading_Thread_Function); // Will return EPERM

このコードは私の端末で実行すると正常に動作します。 "/etc/init.d/myinitdscript start"を呼び出すと、init.dスクリプトでも正常に実行されます。また、「sudo service myinitdscript start」でうまく動作します。 init.dスクリプトには次の内容が含まれています。

#! /bin/sh
### BEGIN INIT INFO
# Provides:          myinitdscript
# Required-Start:    $local_fs $remote_fs $syslog $network
# Required-Stop:     $local_fs $remote_fs $syslog $network
# Default-Start:     3 4 5
# Default-Stop:      0 1 6
# Short-Description: Starts my daemon
# Description:       Verbose explanation of starting my daemon
### END INIT INFO
PATH=/sbin:/usr/sbin:/bin:/usr/bin
LOG=/home/someusershome/initd.log
NAME=myinitdscript
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
[ -x "$DAEMON" ] || (echo "$DAEMON not found. Exiting $SCRIPTNAME." >> $LOG 2>&1 && exit 0)
USERTORUNAS=a_user_on_my_system
SOURCE_SCRIPT=/home/$USERTORUNAS/source_script
DAEMON_ARGS="some_args_for_script"

. /lib/init/vars.sh

. /lib/lsb/init-functions

# Source this script for environmental variables
[ -f $SOURCE_SCRIPT ] && . $SOURCE_SCRIPT

# This is called when called with 'start', I am skipping that for succintness
do_start()
{
    start-stop-daemon --start --make-pidfile --pidfile $PIDFILE --test --background --chuid $USERTORUNAS --startas /bin/bash -- -c "exec $DAEMON -- $DAEMON_ARGS >> $LOG 2>&1 " || return 1
    start-stop-daemon --start --make-pidfile --pidfile $PIDFILE --background --chuid $USERTORUNAS --startas /bin/bash -- -c "exec $DAEMON -- $DAEMON_ARGS >> $LOG 2>&1" || return 2
}

以下を使用してこのinit.dスクリプトを有効にすると:

update-rc.d myinitdscript defaults 99

起動時にエラーが発生し、pthread_createを呼び出すとEPERMエラーが発生します(k = 1、EPERMとも呼ばれます)。 sudo service myinitdscript start を使用して実行でき、正常に実行されます。また、/etc/init.d/myinitdscript start を呼び出すと正常に実行されます。システム起動時にこのスクリプトを実行すると失敗します。

開始 - 停止デーモン呼び出しに "-P fifo:99"オプションを追加すると、優先順位が高すぎる場合を除いて、EPERMエラーが発生せず、コードが正しく実行されることがわかりました。これを修正するには、これを呼び出します。ライブで実行する必要があるコードの唯一の部分は、コードから生成されたpthreadです。したがって、通常、予約済みスレッドで30の優先順位を持つリアルタイムスレッドを作成することは私の権限に関連しているようです。

init.dスクリプトを手動で起動したりサービスを介して実行したりするのではなく、ブートで実行するときにスクリプトに特別な予約ポリシー/優先順位が必要なのはなぜですか?

編集:Ubuntu 12.04で実行されています。

編集2:開始 - 停止デーモン呼び出しが開始されるコードに "ulimit -r"の呼び出しを追加しようとしましたが、無限の制限がありました。私が知っている限り、SCHED_FIFOに権限の問題があってはいけません。 30 そこ

EDIT3:すべてのSystemVスタイルスクリプトを起動するrc-sysinit.confという初期化スクリプトでUpstartを実行していたことがわかりました。たぶんUpstartが私の権限を台無しにしたかもしれません。

ベストアンサー1

答えは、do_startのstart-stop-daemon呼び出しの前に置いたinit.dスクリプトに次のものを置くようです。

ulimit -r ## (where ## is a sufficiently high number; 99 works)

これを確認できた方法は、私のコードのbashコマンド内でulimit -aへのシステムコールを実行することでした。

bash -c "ulimit -a"

ulimit -aはシェル組み込み機能なので、bash部分が必要です。 /bin/shのulimit -aは、リアルタイムの優先順位に関係なく他の情報を返します。何らかの理由で起動時にサービスが開始されると、リアルタイム優先順位が0(リアルタイム優先順位なし)に制限されていることがわかりました。サービスを使用するか、init.dスクリプトを呼び出して実行すると、自分の権限を継承してリアルタイムの優先順位を受け入れます。ただし、システムがUpstart / SystemV以前のバージョンとの互換性システムを介して呼び出されると、昇格された権限が得られません。私の考えでは、これはUpstartが/etc/security/limits.confを読み取らず、/ etc /で権限のないユーザーに対してシステム全体のリアルタイム優先順位を設定できるという投稿に関連している可能性があると思います。 security/limits.conf レベルの権限。

誰かがこのソリューションが機能する理由を確認または説明できる場合は、聞きたいです。

おすすめ記事