CS:APP (13) 썸네일형 리스트형 프로시저 프로시저 호출은 소프트웨어에서 중요한 추상화이다. 이들은 지정된 인자들과 리턴 값으로 특정 기능을 구현하는 코드를 감싸주는 방법을 제공한다. 프로시저에 대한 기계어수준 지원을 제공할 때 처리되어야 하는 여러 가지 많은 특성들이 존재한다. 프로시저 P가 프로시저 Q를 호출하고, Q가 실행한 후에 다시 P로 리턴한다고 가정하자. 이러한 동작들은 다음과 같은 하나 이상의 메커니즘이 연관된다 제어권 전달: PC(프로그램 카운터) 는 진입 할 때 Q에 대한 코드의 시작주소로 설정되고, 리턴할 때는 P에서 Q를 호출하는 명령어 다음의 명령어로 설정되어야 한다. 데이터 전달: P는 하나 이상의 매개변수를 Q에 제공할 수 있어야 하며, Q는 다시 P로 하나의 값을 리턴할 수 있어야 함. 메모리 할당과 반납: Q는 시작.. 전통적 동기화 문제와 데드락 데드락은 동시성 이슈에서 다루는 게 좋을 것 같았지만, 예시와 함께 정리해보려고 한다. Produer-Consumer problem 소비자와 생산자가 유한한 버퍼를 갖는 상황에서 소비자와 생산자가 상호 배타적으로 접근하고, 소비자는 버퍼가 있으면 소비하고 , 생산자는 원소가 없으면 원소를 생성해야 한다. 위의 문제를 해결하려는 조건은 생산자가 우선 실행된 적이 있어야 하고, 생산자의 실행 횟수가 소비자보다 많아야 한다. 이를 해결하기 위해서 3가지 세마포를 사용한다 mutex라는 생산자 소비자 상호 배제를 위한 세마포 slots이라는 비어있는 버퍼의 개수를 나타내는 세마포 items라는 버퍼에 차있는 개수를 나타내는 세마포 여기서 주의할 점은 다음과 같이 코드를 작성해 버리면 데드락에 걸릴 수가 있다. .. 동시성 이슈 동기화는 근본적으로 어려운 문제라고 한다. 어떤 종류의 동시성 흐름이 공유 자원을 조작할 때 발생하는 일반적인 이슈들을 정리해 보자. 스레드 안전 (Thread safety) 쓰레드로 프로그래밍할 때, 스레드 안전성이라고 부르는 특성을 가지는 함수를 작성하도록 유의해야 함. 다수의 동시성 스레드로부터 반복적으로 호출될 때 항상 정확한 결과를 만드는 경우에만 스레드-안전이라고 한다. 병렬 프로그램에서는 단순히 lock만 신경 쓴다고 해결되지 않는 다고 한다. 만일 어떠한 함수가 스레드 안전하지 않다면 이것은 thread-unsafe라 한다. 스레드-위험한 함수의 네 가지 클래스를 다음과 같이 식별할 수 있다. 클래스 1: 공유 변수를 보호하지 않는 함수들 예를 들어 보호되지 않는 전역 변수를 증가시키는 경.. asm (생각나는 대로 정리중) ZF, CF 등 여러 상태가 있는데 ZF는 연산 결과가 0이면 1이고 0이 아니면 0이 된다. CF는 연산 시 비트 올림이나, 비트 내림 발생 시 CF가 1로 set 됨 cmp는 두 operand의 차를 사용해서 비교하는 명령어 연산 결과는 저장 안 됨 차가 0이 되면 ZF가 1로 set 됨 test 명령어는 두 operand AND연산하는 거임 그래서 0인지 판별할 때 많이 함 똑같이 0이면 ZF가 1로 세팅됨 cmp는 두 operand가 완전히 같은지 판단할 수 있고 test는 두 operand가 모두 0인지 판단할 수 있다. test의 경우에는 두 operand가 0이 아닌 경우를 제외하고는 값을 단정 지을 수 없기 때문에 test eax eax 같은 형태로 사용하여 값이 0이 아닌지 파악할 때 씀.. Nonlocal jumps c에서 비지역성 점프라고 부른 사용자 수준의 예외적 제어 흐름의 형태를 제공하며, 이것은 보통의 콜-리턴 순서를 통할 필요 없이 하나의 함수에서 현재 실행하고 있는 다른 함수로 제어를 이동한다. 비지역성 점프는 setjmp와 longjmp함수로 제공한다. setjmp함수는 현재 호출하는 환경을 jmp_buf 타입의 버퍼에 저장해서 후에 longjmp가 사용되며 0을 리턴한다 호출하는 환경은 프로그램 카운터, 스택 포인터, 범용 레지스터를 포함한다. 책에서는 이런 식으로 설명해 주는데, 찾아보니 goto함수는 함수의 범위를 넘어서 이동할 수 없는 제약이 있다고 한다. jmp_buf는 아키텍처별 정보를 담는데 x86의 경우에는 레지스터 정보를 담기 위해 6 개의 정수로 이뤄진다. setjmp() 최초 호출시.. Volatile 지정자 시그널 핸들러 관련해서 CS:APP 책을 읽다가 Volatile 지정자를 쓰는 이유가 정확히 와닿지 않아서 정리해보려고 한다. 검색하면 알 수 있듯이 volatile 지정자는 사용할 때마다 항상 메모리에 접근한다. 이 변수는 언제든 값이 바뀔 수 있으니 메모리에 항상 접근하라고 컴파일러에게 알려주는 것이다. 간단한 예시를 들어서 설명해보자면 int i=10; while (i 시그널 핸들러 작성하기 안전한 시그널의 처리 안전한 핸들러를 작성하는 보수적인 지침들을 알아보자 핸들러는 가능한 간단하게 유지하라 Call only async-signal-safe functions in your handlers. 안전한 함수는 재진입 가능하거나, 어떤 시그널 핸들러에 의해 중단될 수 없기 때문에 어떤 시그널 핸들러로부터 안전하게 호출될 수 있는 특성을 가짐 errno를 저장하고 복원하라, errno를 핸들러에 진입할 때 지역변수에 저장하고, 핸들러가 리턴하기 전에 복원함 전역 변수들은 volatile로 선언하라. 컴파일러는 레지스터에 캐시 되어 있는 g값을 사용해도 안전할 것처럼 생각해서 갱신 값이 안 보일 수가 있다.(자세한 이유는 여기로 --> https://kspsd.tistory.com/40) 정확한 .. 네트워크 프로그래밍 (수정중) 네트워크 애플리케이션들은 동일한 기본적인 프로그래밍 모델에 기초하고 있다. 이들은 비슷한 전체 논리 구조를 가지며, 동일한 프로그래밍 인터페이스를 사용한다. 11.1 클라이 언트-서버 프로그래밍 모델 모든 네트워크 애플리케이션 프로그램은 클라이언트-서버 모델에 기초하고 있다. 클라이언트-서버 모델에서 근본적인 연산은 트랜잭션이다. 클라이언트-서버 트랜잭션은 4단계로 구성된다. (여기서 말하는 트랜잭션은 DB에서 말하는 트랜잭션과는 다르다. 단순한 수행한 일련의 단계를 의미함) 클라이언트가 서비스를 필요할 때, 한 개의 요청을 서버로 보내는 것으로 트랜잭션을 게시. 서버는 요청을 받고 해석후 자신의 자원들을 적절한 방법으로 조작. 예를 들어 웹 서버가 브라우저로부터 요청받으면 디스크 파일을 읽음 서버는 응.. 이전 1 2 다음