[블로그 통합으로 이전해 온 자료] - 2008. 4. 24. 17:40
* semaphore/mutex
* semaphore 변수를 이용해 프로세스의 임계영역 접근을 제어한다.
임계영역에 들어가기 전에 down_*() 함수를 사용해서 semaphore를 잡고
임계영역이 끝나면 up() 함수로 semaphore를 풀어준다.
<asm/semaphore.h>
void sema_init( struct semaphore *sem, int val );
DECLARE_MUTEX( name );
DECLARE_MUTEX_LOCKED( name );
void init_MUTEX( struct semaphore *sem );
void init_MUTEX_LOCKED( struct semaphore *sem );
void down( struct semaphore *sem );
int down_interruptible( struct semaphore *sem ); <-- 주로 사용하는게 좋다.
int donw_trylock( struct semaphore *sem ); <-- 프로세스를 잠들게하지 않는다.
void up( struct semaphore *sem );
<asm/rwsem.h> <-- 사용하지 않는 편이 좋다.
void init_rwsem( struct rw_semaphore *sem );
void down_read( struct rw_semaphore *sem );
int down_read_trylock( struct rw_semaphore *sem );
void up_read( struct rw_semaphore *sem );
void down_write( struct rw_semaphore *sem );
int down_write_trylock( struct rw_semaphore *sem );
void up_write( struct rw_semaphore *sem );
void downgrade_write( struct rw_semaphore *sem );
<linux/completion.h> <-- 한번의 사용을 위해서..
DECLARE_COMPLETION( my_completion );
INIT_COMPLETION( my_completion );
struct completion my_completion;
init_completion( &my_completion );
void wait_for_completion( struct completion *c );
void complete( struct completion *c );
void complete_all( struct completion *c );
* spinlock
* smp 시스템을 위한 lock (단일 cpu 시스템에서는 쓰지 말자)
* 비 선점형 단일 프로세서 시스템에서는 아무것도 하지 않는다는데
그렇다면 선점형 단일 프로세서 시스템에서는??
스핀락을 기다리는 동안은 인터럽트가 불가능하다.
***
스핀락을 쥐고 있는 동안에 수행할 코드는 어떠한 상황에서도 잠지기 상태에
빠져서는 안된다. (인터럽트조자 걸려서는 안되는 경우도 있다고 한다.)
kmalloc(), copy_*_user() 류의 함수와 같은 코드 사용은 스핀락 영역 밖에서 사용할것!!
<linux/spinlock.h>
spinlock_t my_lock = SPIN_LOCK_UNLOCKED;
void spin_lock_init( spinlock_t *lock );
void spin_lock( spinlock_t *lock ); <-- 인터럽트 none disable, 인터럽트 핸들러에서 사용불가
void spin_lock_irqsave( spinlock_t *lock, unsigned long flags ); <-- 인터럽트 disable
void spin_lock_irq( spinlock_t *lock ); <-- 인터럽트 disable
void spin_lock_bh( spinlock_t *lock ); <-- softirq disable
void spin_unlock( spinlock_t *lock );
void spin_unlock_irqstore( spinlock_t *lock, unsigned long flags );
void spin_unlock_irq( spinlock_t *lock );
void spin_unlock_bh( spinlock_t *lock );
<linux/spinlock.h> <-- 역시나 사용하지 않는 편이 좋다.
rwlock_t mylock = RW_LOCK_UNLOCKED;
rwlock_t mylock;
rwlock_init( &mylock );
void read/write_un/lock( rwlock_t *lock );
void read/write_un/lock_irqsave( rwlock_t *lock, unsigned long flags );
void read/write_un/lock_irq( rwlock_t *lock );
void read/write_un/lock_bh( rwlock_t *lock );
int write_trylock( rwlock_t *lock );
* atomic var
* 정수형태만 사용 가능하며 여러개의 동작을 할 경우는 잠금이 필수~!
<asm/atomic.h>
atomic_t = ATOMIC_INIT( n );
void atomic_set( atomic_t *v, init i );
int atomic_read( atomic_t *t );
void atomic_add( int i, atomic_t *v );
void atomic_sub( int i, atomic_t *v );
void atomic_inc( atomic_t *v );
void atomic_dec( atomic_t *v );
int atomic_sub_and_test( int i, atomic_t *v );
int atomic_inc_and_test( atomic_t *v );
int atomic_dec_and_test( atomic_t *v );
int atomic_add_negative( int i, atomic_t *v );
int atomic_add_return( int i, atomic_t *v );
int atomic_sub_return( int i, atomic_t *v );
int atomic_inc_return( atomic_t *v );
int atomic_dec_return( atomic_t *v );
* bit operation
<asm/bitops.h>
void set_bit( nr, void *addr );
void clear_bit( nr, void *addr );
void change_bit( nr, void *addr );
int test_bit( nr, void *addr );
int test_and_set_bit( nr, void *addr );
int test_and_clear_bit( nr, void *addr );
int test_and_change_bit( nr, void *addr );
* seqlock
* 보호 자원이 작고, 간단하고 접근이 잦을 때, 그리고 쓰기 접근이 드물지만 빨라야 할 때 적당
* 일기 쓰레드가 스스로 쓰기 쓰레드와 충돌을 확인해야 하며 충돌이 발생하면 접긍늘 다시 한번 시도해야한다.
* 포인터가 있는 자료 구조체를 보호하는 데는 적합하지 않다.
<linux/seqlock.h>
seqlock_t lock1 = SEQLOCK_UNLOCKED;
seqlock_t lock2;
seqlock_init( &lock2 );
example>
unsigned int seq;
do
{
seq = read_seqbegin( &lock2 );
} wile ( read_seqretry( &lock2, seq ) );
- 읽기 쓰레드
unsigned int read_seqbegin( seqlock_t *lock, unsigned long flags );
int read_seqretry( seqlock_t *lock, unsigned int seq, unsigned long flags );
unsigned int read_seqbegin_irqsave( seqlock_t *lock, unsigned long flags );
int read_seqretry_irqrestore( seqlock_t *lock, unsigned int seq, unsigned long flags );
- 쓰기 쓰레드
void write_seqlock( seqlock_t *lock );
void write_seqlock_irqsave( seqlock_t *lock, unsigned long flags );
void write_seqlock_irq( seqlock_t *lock );
void write_seqlock_bh( seqlock_t *lock );
void write_sequnlock( seqlock_t *lock );
void write_sequnlock_irqrestore( seqlock_t *lock, unsigned long flags );
void write_sequnlock_irq( seqlock_t *lock );
void write_sequnlock_bh( seqlock_t *lock );
'실습 > 리눅스 커널' 카테고리의 다른 글
커널 타이머, 태스크릿, 작업큐 (0) | 2021.02.08 |
---|---|
드라이버 코드의 실행 지연 (0) | 2021.02.08 |
커널에서 Blocking I/O (0) | 2021.02.08 |
Kernel Module 컴파일을 위한 Makefile 만들기 (0) | 2021.02.08 |
Kernel Module - template (0) | 2021.02.08 |