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 수준 권한.
누군가 이 솔루션이 작동하는 이유를 확인하거나 설명할 수 있다면 듣고 싶습니다.