2011-08-29 6 views
1

커널을 거치지 않고 다른 프로세스에서 스레드를 깨울 수있는 메커니즘이 있습니까? 대기중인 스레드는 루프에서 회전 할 수 있지만 아무 문제가 없습니다 (각 스레드는 별도의 코어로 연결됨). 그러나 제 경우에는 보내는 스레드가 빠르며 커널을 통해 대기 스레드를 깨울 여유가 없습니다 .커널 지원없이 스레드 깨우기

+0

'sem_post'가 얼마나 빠르지, 커널의 도움없이 스레드를 조정할 방법을 찾고 있습니까? –

+0

나중에. 게시물을 편집했습니다. – MetallicPriest

+0

질문을 다시 읽는 것은 커널 호출없이 "프로세스 간 통신"을 수행하는 방법에 관한 것입니까? –

답변

4

아니요, 다른 스레드가 절전 모드 일 때 (CPU가 아님) 아니오. 그런 스레드를 깨우려면 커널의 일부인 스케줄러를 호출하여 상태를 "실행 중"으로 변경해야합니다.

예, 두 CPU가 서로 다른 CPU에서 실행 중이고 둘 사이에 공유 메모리가있는 경우 두 스레드 또는 프로세스를 동기화 할 수 있습니다. 모든 스레드를 다른 CPU에 바인드해야합니다. 그런 다음 POSIX의 Pthread ('(ADVANCED REALTIME THREADS)'; [THR SPI])의 선택적 부분에서 spinlock : pthread_spin_lockpthread_spin_unlock 함수를 사용할 수 있습니다. 또는 맞춤 스핀 록 중 하나를 선택합니다. 사용자 정의 스핀 락은 원자 조작 및/또는 메모리 장벽을 사용합니다.

송신 스레드는 메모리의 값을 변경하며 수신기 스레드의 루프에서 확인됩니다.

예.

초기화 :

pthread_spinlock_t lock; 
pthread_spin_lock(&lock); // close the "mutex" 

다음 스레드를 시작합니다.

대기 스레드 :

{ 
pthread_spin_lock(&lock); // wait for event; 
work(); 
} 

메인 스레드 :

{ 
do_smth(); 
pthread_spin_unlock(&lock); // open the mutex; other thread will see this change 
// in ~150 CPU ticks (checked on Pentium4 and Intel Core2 single socket systems); 
// time of the operation itself is of the same order; didn't measure it. 
continue_work(); 
} 
1

커널 호출에 시간을 보내고 발신자를 시작하지 않고, 그것을 계속해야 다른 과정에 신호를 하나의 메커니즘 바로 떠오른다. 커널 호출없이 모든 프로세스가 할 수있는 일은 메모리를 수정하는 것입니다. 그래서 해결책은 inter-process shared memory입니다. 송신자가 공유 메모리에 기록을하면, 수신기는 명시 적 커널 호출없이 변경 사항을 확인해야하며 수신자가 순진한 폴링을 잘 수행해야합니다.

하나의 저렴한 (그러나 아마도 충분하지 않을 수도 있습니다) 대안은 같은 프로세스에서 도우미 스레드로 보내는 것을 위임하고 도우미 스레드가 적절한 세마포어 릴리스 "세마포어 릴리스"또는 파이프 쓰기 호출을하도록합니다.

+0

파이프는 OS 기반 방법입니다. 매 동기화마다'write'와'read' 시스템 호출이 있습니다. – osgx

+0

@osgx : [libeio] (http://software.schmorp.de/pkg/libeio.html)와 같은 비동기 I/O 라이브러리는 바닐라'write' 및'read' 호출을 사용합니까? –

+0

클래식 UNIX 파이프는 OS 지원 구조입니다. libeio의 경우 : "이것은 매우 이식성이 뛰어나며 POSIX 스레드에만 의존합니다."따라서 "다른 대안이 위임됩니다". [이 파일의 918 번과 934 행을 확인하십시오] (http://cvs.schmorp.de/libeio/eio.c?revision=1.102&view=markup) – osgx

0

커널 관련 오버 헤드를 피하기 위해 커널을 사용하지 않으려는 것으로 알고 있습니다. 이러한 오버 헤드의 대부분은 컨텍스트 스위치 관련입니다. 다음은 회전하지 않고 신호를 사용하여 필요한 것을 수행하는 하나의 방법의 데모이며, 맥락없이 전환 :이 코드를 실행하면, 당신은 자식 스레드가 SIGRTMIN를 수신 유지 것을 볼 수 있습니다

#include <signal.h> 
#include <unistd.h> 
#include <sys/syscall.h> 
#include <pthread.h> 
#include <iostream> 
#include <thread> 

using namespace std; 

void sigRtHandler(int sig) { 
    cout << "Recevied signal" << endl; 
} 

int main() { 
    constexpr static int kIter = 100000; 
    thread t([]() { 
     signal(SIGRTMIN, sigRtHandler); 
     for (int i = 0; i < kIter; ++i) { 
      usleep(1000); 
     } 
     cout << "Done" << endl; 
    }); 
    usleep(1000); // Give child time to setup signal handler. 
    auto handle = t.native_handle(); 
    for (int i = 0; i < kIter; ++i) 
     pthread_kill(handle, SIGRTMIN); 
    t.join(); 
    return 0; 
} 

. 프로세스가 실행 중일 때이 프로세스의/proc/(PID)/task/*/status 파일을 보면 부모 스레드가 컨텍스트 스위치가 pthread_kill()을 호출하지 않는다는 것을 알 수 있습니다.

이 방법의 장점은 대기중인 스레드가 회전 할 필요가 없다는 것입니다. 대기중인 스레드의 작업이 시간에 민감하지 않은 경우이 방법을 사용하면 CPU를 절약 할 수 있습니다.

관련 문제