문제

이 시나리오에 대한 잠금 문제를 해결해야합니다.

  1. 멀티 CPU 시스템.
  2. 모든 CPU의 모든 공통 (소프트웨어) 리소스를 사용합니다.
  3. 리소스에 대한 액세스 만 읽기는 매우 일반적입니다. (들어오는 네트워크 패킷 처리)
  4. 쓰기 액세스는 훨씬 덜 빈번합니다. (거의 많은 구성 만 변경).

현재 나는 그것을 사용한다 read_lock_bh, write_lock_bh (스핀 락) 메커니즘. 문제는 CPU가 많을수록 작가 맥락에서 더 많은 잠금을 얻는다는 것입니다.

동시성 장을 읽었습니다 이 책, 그러나 스핀 잠금 장치를 사용할 때 독자 나 작가가 우선 순위가 있는지 이해할 수 없었습니다.

그래서 질문은 다음과 같습니다.

  1. Linux Spinlock 메커니즘은 독자/작가/아무도 우선 순위를 부여합니까?
  2. 시나리오에서 소프트 잠금을 피하기 위해 사용할 수있는 더 나은 메커니즘이 있습니까, 아니면 현재 솔루션을 사용하는 동안 잠금을 얻으려고 할 때마다 작가에게 우선 순위를 부여하는 방법이 있습니까?

감사합니다, Nir

도움이 되었습니까?

해결책

다음은 직접 인용문입니다 필수 리눅스 장치 드라이버 당신이 찾고있는 것일 수도 있습니다. 결국 RCU를 다루는 부분이 당신이 관심있는 것일 수 있습니다.

독자 작가 잠금

또 다른 특수 동시성 조절 메커니즘은 스핀 락의 독자 작성자 변형입니다. 임계 섹션의 사용이 별도의 스레드가 공유 데이터 구조에서 읽거나 쓰는 것이지만 두 가지 모두를 수행하지 않으면 이러한 잠금 장치는 자연스럽게 맞습니다. 임계 영역 내부에서 동시에 여러 리더 스레드가 허용됩니다. 리더 스핀 록은 다음과 같이 정의됩니다.

rwlock_t myrwlock = RW_LOCK_UNLOCKED;

read_lock(&myrwlock);             /* Acquire reader lock */
/* ... Critical Region ... */
read_unlock(&myrwlock);           /* Release lock */

그러나 작가 스레드가 중요한 섹션에 들어가면 다른 독자 또는 작가 스레드는 내부에 허용되지 않습니다. Writer Spinlocks를 사용하려면 다음을 작성합니다.

rwlock_t myrwlock = RW_LOCK_UNLOCKED;

write_lock(&myrwlock);            /* Acquire writer lock */
/* ... Critical Region ... */
write_unlock(&myrwlock); /* Release lock */

존재하는 IPX 라우팅 코드를보십시오 net/ipx/ipx_route.c 독자 작가 스피 록의 실제 예. 독자 작가 잠금 장치 ipx_routes_lock IPX 라우팅 테이블을 동시 액세스로부터 보호합니다. 패킷을 전달하기 위해 라우팅 테이블을 찾아야하는 스레드는 리더 잠금을 요청합니다. 라우팅 테이블에서 항목을 추가하거나 삭제 해야하는 스레드는 작가 잠금 장치를 얻습니다. 라우팅 테이블 업데이트보다 훨씬 더 많은 라우팅 테이블 조회 인스턴스가 있기 때문에 성능이 향상됩니다.

일반 스핀 록과 마찬가지로 리더기 작가 잠금 장치에는 해당 IRQ 변형, 즉, read_lock_irqsave(), read_lock_irqrestore(), write_lock_irqsave(), 그리고 write_lock_irqrestore(). 이러한 기능의 의미는 일반 스핀 락의 의미와 유사합니다.

2.6 커널에 도입 된 시퀀스 잠금 장치 또는 Seqlocks는 독자보다 작가가 선호하는 독자 작가 잠금 장치입니다. 이는 가변적으로 멀리 떨어진 읽기 액세스에 대한 쓰기 작업이 유용합니다. 예는 다음과 같습니다jiffies_64 이 장의 앞부분에서 논의 된 변수. 작가 스레드는 중요한 섹션 안에있을 수있는 독자를 기다리지 않습니다. 이로 인해 리더 스레드는 임계 섹션 내부의 항목이 실패했으며 다시 시도해야 할 수 있음을 발견 할 수 있습니다.

u64 get_jiffies_64(void) /* Defined in kernel/time.c */
{
   unsigned long seq;
   u64 ret;
   do {
      seq = read_seqbegin(&xtime_lock);
      ret = jiffies_64;
   } while (read_seqretry(&xtime_lock, seq));
   return ret;
}

작가는 사용을 사용하여 중요한 지역을 보호합니다 write_seqlock() 그리고 write_sequnlock().

2.6 커널은 또 다른 메커니즘을 소개했습니다 Read-Copy Update (RCU), 독자가 작가보다 훨씬 많을 때 성능이 향상되었습니다. 기본 아이디어는 리더 스레드가 잠금없이 실행할 수 있다는 것입니다. 작가 스레드는 더 복잡합니다. 데이터 구조 사본에서 업데이트 작업을 수행하고 독자가 보는 포인터를 대체합니다. 원래 사본은 모든 CPU의 다음 컨텍스트 스위치까지 유지하여 모든 진행중인 읽기 작업의 완료를 보장합니다. RCU를 사용하는 것이 지금까지 논의 된 프리미티브를 사용하는 것보다 더 관여하고 있으며 그것이 작업에 적합한 도구라고 확신하는 경우에만 사용해야합니다. RCU 데이터 구조 및 인터페이스 함수는 정의됩니다 include/linux/rcupdate.h. 충분한 문서가 있습니다Documentation/RCU/*.

RCU 사용 예제, 보다 fs/dcache.c. Linux에서 각 파일은 디렉토리 입력 정보 (Dentry라고하는 구조에 저장), 메타 데이터 정보 (inode에 저장) 및 실제 데이터 (데이터 블록에 저장)와 관련이 있습니다. 파일에서 작동 할 때마다 파일 경로의 구성 요소가 구문 분석되고 해당 덴트리가 얻어집니다. Dentries는 향후 운영 속도를 높이기 위해 DCACHE라는 데이터 구조로 캐싱됩니다. 언제든지 DCACHE 조회의 수는 DCACHE 업데이트보다 훨씬 많으므로 DCACHE에 대한 참조는 RCU 프리미티브를 사용하여 보호됩니다.

다른 팁

RCU가 처리하도록 설계된 종류의 사용 케이스가 아닌가? 보다 http://lwn.net/articles/262464/ 그것에 대한 좋은 글을 쓰려면.

자물쇠를 잡고있는 동안하는 작업이 작 으면 독자가 아닌 일반적인 뮤 테스를 시도 할 수 있습니다. 더 효율적입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top