Linux系统编程——进程间通信:信号中断处理

什么是信号?

信号是 Linux 进程间通信的最古老的方式。信号是

url=474nN303T2Oe2ehYZjkrggeXCaJPDSrmM5Unoh4TTuty4wSgS0nl4-vl43AGMFbo0_5uH5OQFr_vaRJaZ-3lq_" style="color:rgb(202,0,0); text-decoration:none">软件中断,它是在软件层次上对中断机制的一种模拟,是一种异步通信的方式 。

信号能够导致一个正在执行的进程被还有一个正在执行的异步进程中断,转而处理某一个突发事件。

“中断”在我们生活中常常遇到。譬如,我正在房间里打游戏。突然送快递的来了。把正在玩游戏的我给“中断”了,我去签收快递( 处理中断 ),处理完毕后,再继续玩我的游戏。

这里我们学习的“信号”就是属于这么一种“中断”。我们在终端上敲“Ctrl+c”。就产生一个“中断”,相当于产生一个信号,接着就会处理这么一个“中断任务”(默认的处理方式为中断当前进程)。

信号能够直接进行用户空间进程和内核空间进程的交互。内核进程能够利用它来通知用户空间进程发生了哪些系统事件。

一个完整的信号周期包含三个部分:信号的产生,信号在进程中的注冊,信号在进程中的注销。运行信号处理函数。

例如以下图所看到的:

注意:这里信号的产生,注冊。注销时信号的内部机制。而不是信号的函数实现。

Linux 可使用命令:kill -l("l" 为字母),查看对应的信号。

列表中,编号为 1 ~ 31的信号为传统 UNIX 支持的信号,是不可靠信号(非实时的)。编号为32 ~ 63的信号是后来扩充的。称做可靠信号(实时信号)。不可靠信号和可靠信号的差别在于前者不支持排队,可能会造成信号丢失,而后者不会。非可靠信号一般都有确定的用途及含义,
 可靠信号则能够让用户自己定义使用。很多其它详情。请看《Linux信号列表》。

信号的产生方式

信号的经常使用操作

1)当用户按某些终端键时。将产生信号。

终端上按“Ctrl+c”组合键通常产生中断信号 SIGINT,终端上按“Ctrl+\”键通常产生中断信号 SIGQUIT,终端上按“Ctrl+z”键通常产生中断信号 SIGSTOP 等。

2)硬件异常将产生信号。

除数为 0,无效的内存訪问等。这些情况通常由硬件检測到,并通知内核。然后内核产生适当的信号发送给对应的进程。

3)软件异常将产生信号。

当检測到某种软件条件已发生,并将其通知有关进程时,产生信号。

4)调用 kill() 函数将发送信号。

注意:接收信号进程和发送信号进程的全部者必须同样,或发送信号进程的全部者必须是超级用户。

5)执行 kill 命令将发送信号。

此程序实际上是使用 kill 函数来发送信号。

也经常使用此命令终止一个失控的后台进程。

信号的经常使用操作:

发送信号

所需头文件:

#include <sys/types.h>

#include <signal.h>

int kill(pid_t pid, intsignum);

功能:

给指定进程发送信号。

注意:使用 kill() 函数发送信号,接收信号进程和发送信号进程的全部者必须同样,或者发送信号进程的全部者是超级用户。

參数:

pid: 取值有 4 种情况:

pid > 0: 将信号传送给进程 ID 为pid的进程。

pid = 0: 将信号传送给当前进程所在进程组中的全部进程。

pid = -1: 将信号传送给系统内全部的进程。

pid < -1: 将信号传给指定进程组的全部进程。这个进程组号等于 pid 的绝对值。

signum: 信号的编号,这里能够填数字编号,也能够填信号的宏定义,能够通过命令kill -l ("l" 为字母)进行对应查看。

返回值:

成功:0

失败:-1

以下为測试代码,本来父子进程各自每隔一秒打印一句话,3 秒后,父进程通过 kill() 函数给子进程发送一个中断信号 SIGINT( 2 号信号),终于。子进程结束。剩下父进程在信息打印:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>  

int main(int argc, char *argv[])
{
    pid_t pid;
    int i = 0;  

    pid = fork(); // 创建进程
    if( pid < 0 ){ // 出错
        perror("fork");
    }  

    if(pid == 0){ // 子进程
        while(1){
            printf("I am son\n");
            sleep(1);
        }
    }else if(pid > 0){ // 父进程
        while(1){
            printf("I am father\n");
            sleep(1);  

            i++;
            if(3 == i){// 3秒后
                kill(pid, SIGINT); // 给子进程 pid 。发送中断信号 SIGINT
                // kill(pid, 2); // 等级于kill(pid, SIGINT);
            }
        }
    }  

    return 0;
}

执行结果:

等待信号

所需头文件:

#include <unistd.h>

int pause(void);

功能:

等待信号的到来(此函数会堵塞)。将调用进程挂起直至捕捉到信号为止,此函数通经常使用于推断信号是否已到。

參数:

无。

返回值:

直到捕获到信号才返回 -1。且 errno 被设置成 EINTR。

測试代码例如以下:

#include <unistd.h>
#include <stdio.h>  

int main(int argc, char *argv[])
{
    printf("in pause function\n");
    pause();  

    return 0;
}  

没有产生信号前。进程一直堵塞在 pause() 不会往下运行。假如,我们按“Ctrl+c”,pause() 会捕获到此信号。中断当前进程

处理信号

一个进程收到一个信号的时候,能够用例如以下方法进行处理:

1)运行系统默认动作

对大多数信号来说,系统默认动作是用来终止该进程。

2)忽略此信号

接收到此信号后没有不论什么动作。

3)运行自己定义信号处理函数

用用户定义的信号处理函数处理该信号。

注意:SIGKILL 和 SIGSTOP 不能更改信号的处理方式,由于它们向用户提供了一种使进程终止的可靠方法。

产生一个信号,我们能够让其运行自己定义信号处理函数。假如有函数 A, B, C,我们怎样确定信号产生后仅仅调用函数 A。而不是函数 B 或 C。这时候。我们须要一种规则规定,信号产生后就调用函数 A,就像交通规则一样。红灯走绿灯行,信号注冊函数 signal() 就是做这种事情。

所需头文件:

#include <signal.h>

typedef void (*sighandler_t)(int);// 回调函数的声明

sighandler_t signal(int signum,sighandler_t handler);

功能:

注冊信号处理函数(不可用于 SIGKILL、SIGSTOP 信号),即确定收到信号后处理函数的入口地址。

此函数不会堵塞。

參数:

signum:信号的编号,这里能够填数字编号,也能够填信号的宏定义,能够通过命令 kill -l ("l" 为字母)进行对应查看。

handler: 取值有 3 种情况:

SIG_IGN:忽略该信号

SIG_DFL:运行系统默认动作

信号处理函数名:自己定义信号处理函数,如:fun

回调函数的定义例如以下:

void fun(int signo)

{

// signo 为触发的信号,为 signal() 第一个參数的值

}

注意:信号处理函数应该为可重入函数。关于可重入函数的很多其它详情。请《浅谈可重入函数与不可重入函数》。

返回值:

成功:第一次返回 NULL。下一次返回此信号上一次注冊的信号处理函数的地址。

假设须要使用此返回值。必须在前面先声明此函数指针的类型。

失败:返回 SIG_ERR

实例1:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

// 信号处理函数
void signal_handler(int signo)
{
	if(signo == SIGINT){
		printf("recv SIGINT\n");
	}else if(signo == SIGQUIT){
		printf("recv SIGQUIT\n");
	}
}

int main(int argc, char *argv[])
{
	printf("wait for SIGINT OR SIGQUIT\n");

	/* SIGINT: Ctrl+c ; SIGQUIT: Ctrl+\ */
	// 信号注冊函数
	signal(SIGINT, signal_handler);
	signal(SIGQUIT, signal_handler);

	// 等待信号
	pause();
	pause();

	return 0;
}

执行结果

实例2:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

// 回调函数的声明
typedef void (*sighandler_t)(int);

void fun1(int signo)
{
	printf("in fun1\n");
}

void fun2(int signo)
{
	printf("in fun2\n");
}

int main(int argc, char *argv[])
{
	sighandler_t previous = NULL;

	// 第一次返回 NULL
	previous = signal(SIGINT,fun1);
	if(previous == NULL)
	{
		printf("return fun addr is NULL\n");
	}

	// 下一次返回此信号上一次注冊的信号处理函数的地址。
	previous = signal(SIGINT, fun2);
	if(previous == fun1)
	{
		printf("return fun addr is fun1\n");
	}

	// 还是返回 NULL,由于处理的信号变了
	previous = signal(SIGQUIT,fun1);
	if(previous == NULL)
	{
		printf("return fun addr is NULL\n");
	}

	return 0;
}

执行结果:

信号集与信号堵塞集

信号集

为了方便对多个信号进行处理。一个用户进程经常须要对多个信号做出处理,在 Linux 系统中引入了信号集(信号的集合)。

这个信号集有点类似于我们的 QQ 群,一个个的信号相当于 QQ 群里的一个个好友。

信号集是用来表示多个信号的数据类型(sigset_t),其定义路径为:/usr/include/i386-linux-gnu/bits/sigset.h。

信号集相关的操作主要有例如以下几个函数:

#include <signal.h>
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigismember(const sigset_t *set, int signum);
int sigaddset(sigset_t *set, int signum);
int sigdelset(sigset_t *set, int signum);

通过样例来查看他的用法:

#include <signal.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
	sigset_t set;	// 定义一个信号集变量
	int ret = 0;

	sigemptyset(&set); // 清空信号集的内容

	// 推断 SIGINT 是否在信号集 set 里
	// 在返回 1, 不在返回 0
	ret = sigismember(&set, SIGINT);
	if(ret == 0){
		printf("SIGINT is not a member of set \nret = %d\n", ret);
	}

	sigaddset(&set, SIGINT); // 把 SIGINT 加入到信号集 set
	sigaddset(&set, SIGQUIT);// 把 SIGQUIT 加入到信号集 set

	// 推断 SIGINT 是否在信号集 set 里
	// 在返回 1, 不在返回 0
	ret = sigismember(&set, SIGINT);
	if(ret == 1){
		printf("SIGINT is a member of set \nret = %d\n", ret);
	}

	sigdelset(&set, SIGQUIT); // 把 SIGQUIT 从信号集 set 移除

	// 推断 SIGQUIT 是否在信号集 set 里
	// 在返回 1, 不在返回 0
	ret = sigismember(&set, SIGQUIT);
	if(ret == 0){
		printf("SIGQUIT is not a member of set \nret = %d\n", ret);
	}

	return 0;
}

执行结果:

信号堵塞集(屏蔽集、掩码)

信号堵塞集也称信号屏蔽集、信号掩码。每一个进程都有一个堵塞集,创建子进程时子进程将继承父进程的堵塞集。信号堵塞集用来描写叙述哪些信号递送到该进程的时候被堵塞(在信号发生时记住它。直到进程准备好时再将信号通知进程)。

所谓堵塞并非禁止传送信号, 而是暂缓信号的传送。若将被堵塞的信号从信号堵塞集中删除,且相应的信号在被堵塞时发生了。进程将会收到相应的信号。

我们能够通过 sigprocmask() 改动当前的信号掩码来改变信号的堵塞情况。

所需头文件:

#include <signal.h>

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

功能:

检查或改动信号堵塞集,依据 how 指定的方法对进程的堵塞集合进行改动,新的信号堵塞集由 set 指定。而原先的信号堵塞集合由 oldset 保存。

參数:

how: 信号堵塞集合的改动方法,有 3 种情况:

SIG_BLOCK:向信号堵塞集合中加入 set 信号集。新的信号掩码是set和旧信号掩码的并集。

SIG_UNBLOCK:从信号堵塞集合中删除 set 信号集,从当前信号掩码中去除 set 中的信号。

SIG_SETMASK:将信号堵塞集合设为 set 信号集。相当于原来信号堵塞集的内容清空,然后依照 set 中的信号又一次设置信号堵塞集。

set: 要操作的信号集地址。

若 set 为 NULL,则不改变信号堵塞集合,函数仅仅把当前信号堵塞集合保存到 oldset 中。

oldset: 保存原先信号堵塞集地址

返回值:

成功:0,

失败:-1,失败时错误代码仅仅可能是 EINVAL。表示參数 how 不合法。

注意:不能堵塞 SIGKILL 和 SIGSTOP 等信号。可是当 set 參数包括这些信号时 sigprocmask() 不返回错误,仅仅是忽略它们。

另外,堵塞 SIGFPE 这种信号可能导致不可挽回的结果,由于这些信号是由程序错误产生的。忽略它们仅仅能导致程序无法运行而被终止。

演示样例代码例如以下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

int main(int argc, char *argv[])
{
	sigset_t set; // 信号集合
	int i = 0;

	sigemptyset(&set); // 清空信号集合
	sigaddset(&set, SIGINT); // SIGINT 增加 set 集合

	while(1)
	{
		// set 集合增加堵塞集,在没有移除前,SIGINT 会被堵塞
		sigprocmask(SIG_BLOCK, &set, NULL);
		for(i=0; i<5; i++)
		{
			printf("SIGINT signal is blocked\n");
			sleep(1);
		}

		// set 集合从堵塞集中移除
		// 假如 SIGINT 信号在被堵塞时发生了
		// 此刻,SIGINT 信号立刻生效。中断当前进程
		sigprocmask(SIG_UNBLOCK, &set, NULL);
		for(i=0; i<5; i++)
		{
			printf("SIGINT signal unblocked\n");
			sleep(1);
		}
	}

	return 0;
}

执行结果:

可靠信号的操作

从 UNIX 系统继承过来的信号(SIGHUP~SIGSYS。前 32 个)都是不可靠信号,不支持排队(多次发送同样的信号, 进程可能仅仅能收到一次,可能会丢失)。

SIGRTMIN 至 SIGRTMAX 的信号支持排队(发多少次, 就能够收到多少次, 不会丢失),故称为可靠信号。

可靠信号就是实时信号,非可靠信号就是非实时信号。

signal() 函数仅仅能提供简单的信号安装操作,使用 signal() 函数处理信号比較简单,仅仅要把要处理的信号和处理函数列出就可以。

signal() 函数主要用于前面 32 种不可靠、非实时信号的处理。而且不支持信号传递信息。

Linux 提供了功能更强大的 sigaction() 函数。此函数能够用来检查和更改信号处理操作,能够支持可靠、实时信号的处理,而且支持信号传递信息。

以下我们一起学习其相关函数的使用。

所需头文件:

#include <signal.h>

int sigqueue(pid_t pid, int sig, const union sigval value);

功能:

给指定进程发送信号。

參数:

pid: 进程号。

sig: 信号的编号。这里能够填数字编号。也能够填信号的宏定义。能够通过命令 kill -l ("l" 为字母)进行对应查看。

value: 通过信号传递的參数。

union sigval 类型例如以下:

[cpp] view
plain
copy

  1. union sigval
  2. {
  3. int   sival_int;
  4. void *sival_ptr;
  5. };

返回值:

成功:0

失败:-1

int sigaction(int signum,const struct sigaction *act, struct
sigaction *oldact );

功能:

检查或改动指定信号的设置(或同一时候运行这两种操作)。

參数:

signum:要操作的信号。

act:   要设置的对信号的新处理方式(设置)。

oldact:原来对信号的处理方式(设置)。

假设 act 指针非空,则要改变指定信号的处理方式(设置),假设 oldact 指针非空,则系统将此前指定信号的处理方式(设置)存入 oldact。

返回值:

成功:0

失败:-1

信号设置结构体:

[cpp] view
plain
copy

  1. struct sigaction
  2. {
  3. /*旧的信号处理函数指针*/
  4. void (*sa_handler)(int signum) ;
  5. /*新的信号处理函数指针*/
  6. void (*sa_sigaction)(int signum, siginfo_t *info, void *context);
  7. sigset_t sa_mask;/*信号堵塞集*/
  8. int sa_flags;/*信号处理的方式*/
  9. };

sa_handler、sa_sigaction:信号处理函数指针,和 signal() 里的函数指针使用方法一样,应依据情况给 sa_sigaction、sa_handler 两者之中的一个赋值,其取值例如以下:

SIG_IGN:忽略该信号

SIG_DFL:运行系统默认动作

处理函数名:自己定义信号处理函数

sa_mask:信号堵塞集

sa_flags:用于指定信号处理的行为,它能够是一下值的“按位或”组合:

SA_RESTART:使被信号打断的系统调用自己主动又一次发起(已经废弃)

SA_NOCLDSTOP:使父进程在它的子进程暂停或继续执行时不会收到 SIGCHLD 信号。

SA_NOCLDWAIT:使父进程在它的子进程退出时不会收到 SIGCHLD 信号,这时子进程假设退出也不会成为僵尸进程。

SA_NODEFER:使对信号的屏蔽无效,即在信号处理函数运行期间仍能发出这个信号。

SA_RESETHAND:信号处理之后又一次设置为默认的处理方式。

SA_SIGINFO:使用 sa_sigaction 成员而不是 sa_handler 作为信号处理函数。

信号处理函数:

void (*sa_sigaction)( int signum, siginfo_t *info, void *context
);

參数说明:

signum:信号的编号。

info:记录信号发送进程信息的结构体,进程信息结构体路径:/usr/include/i386-linux-gnu/bits/siginfo.h,其结构体详情请点此链接

context:能够赋给指向 ucontext_t 类型的一个对象的指针。以引用在传递信号时被中断的接收进程或线程的上下文,其结构体详情点此链接

以下我们做这么一个样例,一个进程在发送信号,一个进程在接收信号的发送。

发送信号演示样例代码:

[cpp] view
plain
copy

  1. #include <stdio.h>
  2. #include <signal.h>
  3. #include <sys/types.h>
  4. #include <unistd.h>
  5. /*******************************************************
  6. *功能:     发 SIGINT 信号及信号携带的值给指定的进程
  7. *參数:        argv[1]:进程号
  8. argv[2]:待发送的值(默觉得100)
  9. *返回值:   0
  10. ********************************************************/
  11. int main(int argc, char *argv[])
  12. {
  13. if(argc >= 2)
  14. {
  15. pid_t pid,pid_self;
  16. union sigval tmp;
  17. pid = atoi(argv[1]); // 进程号
  18. if( argc >= 3 )
  19. {
  20. tmp.sival_int = atoi(argv[2]);
  21. }
  22. else
  23. {
  24. tmp.sival_int = 100;
  25. }
  26. // 给进程 pid。发送 SIGINT 信号,并把 tmp 传递过去
  27. sigqueue(pid, SIGINT, tmp);
  28. pid_self = getpid(); // 进程号
  29. printf("pid = %d, pid_self = %d\n", pid, pid_self);
  30. }
  31. return 0;
  32. }

接收信号演示样例代码例如以下:

[cpp] view
plain
copy

  1. #include <signal.h>
  2. #include <stdio.h>
  3. // 信号处理回电函数
  4. void signal_handler(int signum, siginfo_t *info, void *ptr)
  5. {
  6. printf("signum = %d\n", signum); // 信号编号
  7. printf("info->si_pid = %d\n", info->si_pid); // 对方的进程号
  8. printf("info->si_sigval = %d\n", info->si_value.sival_int); // 对方传递过来的信息
  9. }
  10. int main(int argc, char *argv[])
  11. {
  12. struct sigaction act, oact;
  13. act.sa_sigaction = signal_handler; //指定信号处理回调函数
  14. sigemptyset(&act.sa_mask); // 堵塞集为空
  15. act.sa_flags = SA_SIGINFO; // 指定调用 signal_handler
  16. // 注冊信号 SIGINT
  17. sigaction(SIGINT, &act, &oact);
  18. while(1)
  19. {
  20. printf("pid is %d\n", getpid()); // 进程号
  21. pause(); // 捕获信号,此函数会堵塞
  22. }
  23. return 0;
  24. }

两个终端分别编译代码,一个进程接收。一个进程发送。执行结果例如以下:

源代码下载:http://download.csdn.net/download/lianghe_work/8999733

时间: 2024-10-02 03:10:49

Linux系统编程——进程间通信:信号中断处理的相关文章

linux系统编程之信号(四)

今天继续探讨信号相关的东东,话不多说,正入正题: 信号在内核中的表示: 下面用图来进一步描述这种信号从产生到递达之间的状态(信号阻塞与未诀): 那是怎么来决定的呢?下面慢慢来举例分解: 所以,通过这些图,可以描述信号从产生到递达的一个过程,上面的理解起来可能有点难,下面会用代码来进一步阐述,在进行实验之前,还需了解一些函数的使用,这些函数在实验中都会被用到,也就是信号集操作函数. 信号集操作函数: 其中解释一下sigset_t,百度百科解释为: 而这个函数的意义就是将这64位清0 这个函数的意义

Linux系统编程_10_信号

信号处理机制在linux编程中非常重要,它类似于单片机中的中断系统:我们在编写中断函数时,需要设置中断函数的地址,设置其相应的寄存器,以便于发生中断事件时可以正确的跳到中断函数去执行: linux中信号和这个类似,一般的编程模型是定义中断函数,然后把中断函数注册,使得进程收到特定的信号时,可以跳到信号处理函数去执行: 1.kill函数与raise函数 kill函数用来将信号发送给进程或进程组: --int kill(pid_t pid,  int signo); raise函数则允许进程向自身发

Linux系统编程——进程间通信(一)

基本操作命令: ps -ajx/-aux/-ef 查看进程间状态/的相互关系 top 动态显示系统中的进程 nice 按照指定的优先级运行 /renice 改变正在运行的进程的优先级 kill -9杀死进程 jobs 查看后台进程数 进程的结构.类型.状态.模式 0.Linux中进程包括三段: (1)数据段.存放的是全局变量,常量以及动态内存的数据空间. (2)正文段.存放的是程序中的代码. (3)堆栈段.存放的是函数的返回地址,函数的参数以及局部变量. 进程类型:交互进程,既可以在前台运行,也

Linux系统编程——进程间通信:管道(pipe)

管道的概述 管道也叫无名管道,它是是 UNIX 系统 IPC(进程间通信) 的最古老形式,所有的 UNIX 系统都支持这种通信机制. 无名管道有如下特点: 1.半双工,数据在同一时刻只能在一个方向上流动. 2.数据只能从管道的一端写入,从另一端读出. 3.写入管道中的数据遵循先入先出的规则. 4.管道所传送的数据是无格式的,这要求管道的读出方与写入方必须事先约定好数据的格式,如多少字节算一个消息等. 5.管道不是普通的文件,不属于某个文件系统,其只存在于内存中. 6.管道在内存中对应一个缓冲区.

Linux系统编程——进程间通信:消息队列

消息队列提供了一种在两个不相关的进程之间传递数据的简单高效的方法,其特点如下: 1)消息队列可以实现消息的随机查询.消息不一定要以先进先出的次序读取,编程时可以按消息的类型读取. 2)消息队列允许一个或多个进程向它写入或者读取消息. 3)与无名管道.命名管道一样,从消息队列中读出消息,消息队列中对应的数据都会被删除. 4)每个消息队列都有消息队列标识符,消息队列的标识符在整个系统中是唯一的. 5)消息队列是消息的链表,存放在内存中,由内核维护.只有内核重启或人工删除消息队列时,该消息队列才会被删

Linux系统编程——进程间通信(System V IPC 对象)

基本查看命令 ipcs  -m查看共享内存        ipcs -s查看信号量        ipcs -q查看消息队列 ipcrm  -m  id 删除共享内存   -M+key值 ipcrm  -s  id 删除信号量 ipcrm  -q  id 删除消息队列 (1)共享内存.为了在多个进程间进行信息交换,内核专门留出了一块内存区,可以由需要访问的进程将其映射到自己的私有地址空间.共享内存允许两个或者更多进程共享一给定的存储区,是一种效率最高的进程间通信方式,因为数据不需要再服务端和客户

Linux系统编程——进程间通信:共享内存

概述 共享内存是进程间通信中最简单的方式之一.共享内存允许两个或更多进程访问同一块内存,就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针.当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改. 共享内存的特点: 1)共享内存是进程间共享数据的一种最快的方法. 一个进程向共享的内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容. 2)使用共享内存要注意的是多个进程之间对一个给定存储区访问的互斥. 若一个进程正在向共享内存区写数据,则在它做

Linux系统编程——进程间通信:命名管道(FIFO)

命名管道的概述 无名管道,由于没有名字,只能用于亲缘关系的进程间通信(更多详情,请看<无名管道>).为了克服这个缺点,提出了命名管道(FIFO),也叫有名管道.FIFO 文件. 命名管道(FIFO)不同于无名管道之处在于它提供了一个路径名与之关联,以 FIFO 的文件形式存在于文件系统中,这样,即使与 FIFO 的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过 FIFO 相互通信,因此,通过 FIFO 不相关的进程也能交换数据. 命名管道(FIFO)和无名管道(pipe)有一

linux系统编程视频 百度网盘下载

本帖最后由 雇佣兵333 于 2015-5-19 16:15 编辑 c教程目录: Linux开发快速入门培训gcc快速入门Makefile快速入门GDB快速入门 Linux系统编程之文件篇01认识计算机系统(上)计算机系统组成计算机系统硬件组成总线I/O设备内存处理器(运算器+控制器) 02认识计算机系统(下)什么是操作系统Linux内核模块操作系统管理硬件操作系统三个基本抽象进程上下文切换进程虚地址空间虚拟文件系统(VFS) 03系统编程介绍系统编程与应用编程系统资源系统调用系统调用与C库关系