6.087 Practical Programming in C, lec14

Linux inter process communication

Preliminaries

• Each process has its own address space. Therefore, individualprocesses cannot communicate unlike threads.

• Interprocess communication: Linux/Unix provides several waysto allow communications

  • signal
    pipes
    FIFO queues
    shared memory
    semaphores
    sockets

<signals.h>

• Unix/Linux allows us to handle exceptions that arise duringexecution (e.g., interrupt, floating point error, segmentationfault etc.).

• A process recieves a signal when such a condition occurs.

void (∗signal( int sig,void(∗handler)(int )))( int )

• determines how subsequent signals will be handled.

• pre-defined behavior: SIG_DFL (default), SIG_IGN (ignore)

• returns the previous handler.

这里的exceptions应该就是运行时异常吧,从signal的类型可以得到运行时异常的类别,这个在实际应用中和工作面试中都会经常用到哦:)

Valid signals:

SIGABRT abnormal termination

SIGFPE floating point error

SIGILL illegal instruction

SIGINT interrupt

SIGSEGV segmentation fault

SIGTERM termination request

SIGBUS bus error

SIGQUIT quit

The two signals SIGSTOP,SIGKILL cannot be handled.

<signal.h>

int raise( int sig) can be used to send signal sig to the program.

Notes:

• There can be race conditions.

• signal handler itself can beinterrupted.

• use of non-reentrant functionsunsafe.

• sigprocmask can be used toprevent interruptions.

• handler is reset each time it iscalled.

signal实际上存在共享数据:操作系统中的signal记录,因此线程同步的问题也存在于signal中。

Example

#include <stdio.h>

void sigproc()

{

printf("you have pressed ctrl−c \n");

}

void quitproc()

{

printf("ctrl−\\ pressed toquit");

exit(0); ∗normal exit status∗/

}

main ( )

{

signal(SIGINT, sigproc);

signal(SIGQUIT, quitproc);

printf(‘‘ctrl−c disabled use ctrl−\\ to quit\n’’);

for( ; ; ); /∗infinite loop∗/

}

signal方法的作用是定义接受到某种信号时对应的操作。

Fork

pid_t fork (void)

• fork() is a system call to createa new process

• In the child process, it returns 0

• In the parent process, it returnsthe PID (process id) of the child.

• The child PID can be used to sendsignals to the child process.

• returns -1 on failure (invalidPID)

原来创建一个子进程是如此简单,只需复制自己即可。操作系统自身应该是所有进程的祖先进程。

Example

#include <stdlib.h>

#include <stdio.h>

#include <signal.h>


int main(){

pid_t pid =fork();

int i;

if(pid){

for(i=0;i<5; i++){

sleep(2);

}

printf("parent process: %d\n", i);

}

运行结果:

childprocess: 0

parent process: 0

child process: 1

child process: 2

parent process: 1

child process: 3

child process: 4

parent process: 2

parent process: 3

parent process: 4

Fork

• fork() makes a full copy of the parents address space.

• pid_t getpid() returns PID of the current process.

• pid_t getppid() returns PID of the parent process.

• wait( int∗) is used to wait for the child to finish.

• waitpid () is used to wait for a specific child.

Zombies:

• the child process can exit before the parent

• stray process is marked as <defunct>

• preap can be used to reap zombie processes.

子进程可以在父进程结束之前结束,父进程能否在子进程之前结束呢?我很怀疑,因为子进程有父进程的PID,如果父进程没了,那么这个PID就为空,看起来不怎么舒服。

Pipes

Pipes are used in unix to redirect output of one command toanother. Pipes also allow parent processes to communicate with itschildren.

Examples

• ls | more - displays results of lsone screen at a time

• cat file.txt | sort -displayscontents of file.txt in sorted order

int pipe(int FILEDES[2])

• A pipe can be thought of as a pairof file descriptors

• no physical file is associatedwith the file descriptor

• one end is opened in write mode.

• other end is opened in read mode.

管道在UNIX中是一个十分重要的工具,实现简单但功能强大,很符合UNIXstyle。其实现可以看作用一根两端为fd(filedescriptor)的管道将两个进程连接起来,管道前面的进程会有输出到一个文件,而后面的进程则会读取一个文件。

#include <stdio.h>

#include <stdlib.h>

#include <errno.h>

#include <unistd.h>


int main(void)

{

int pfds[2];

char buf[30];

if (pipe(pfds) == -1) {

perror("pipe");

exit(1);

}

printf("writing to file descriptor#%d\n", pfds[1]);

write(pfds[1], "test", 5);

printf("reading from filedescriptor #%d\n", pfds[0]);

read(pfds[0], buf, 5);

printf("read \"%s\"\n",buf);

return 0;

}

FIFO

• FIFO queues may be thought of as named pipes.

• Multiple processes can read and write from a FIFO.

• Unlike pipes, the processes can be unrelated.

• FIFOs can be created using mknod system call.

intmknod (const char ∗path,mode_t mode,dev_t dev)

• <sys/stat.h> contains the declaration for mknod.

• mknod used to create special files - devices,fifos etc.

• mode can have special bits such as S_IFIFO | 0644

• dev is interpreted based on the mode.

Example: mknod("myfifo", S_IFIFO | 0644 , 0);

FIFO和管道本质上都是使用读写同一个文件的方法实现线程间的通信。

Example

6.087 Practical Programming in C, lec14_第1张图片

你可能感兴趣的:(programming)