设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

操作系统中进程简介

2015-1-27 16:02| 发布者: joejoe0332| 查看: 2711| 评论: 0|原作者: 进林|来自: 伯乐在线

摘要: 很久前我就想写这篇文章了,但总是以各种理由来拖延。操作系统是我日常工作的主要部分,特别是GNU/Linux,这篇文章主要关注GUN/Linux。进程是个大话题,我不确定如何才能覆盖进程的所有知识点。这篇文章将会包含足够 ...


进程间通信(IPC)

  为了进程间的通信,存在两个解决方法,共享内存,消息传递。

  在共享内存的方案里,为了几个进程间能够通信创建了一个共享的区域。这个区域能被多个进程同时访问。这种方法通常在使用线程时使用。这是实现IPC最快的形式,因为这种形式只涉及到内存的读写。 但是,这需要进程在访问共享内存时受到的限制和访问内核实现的其他进程内存一样。

  共享内存段的使用情况可以使用ipcs -m命令查看。

  实现一个共享内存的服务器程序,代码如下:

#include <stdlib.h>
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
 
#define SEGMENT_SIZE 64
 
int main(int argc, char **argv[])
{
int shmid;
char *shmaddr;
 
/* Create or get the shared memory segment */
if ((shmid = shmget(555, SEGMENT_SIZE, 0644 | IPC_CREAT)) == -1) {
printf("Error: Could not get memory segmentn");
exit(EXIT_FAILURE);
}
 
/* Attach to the shared memory segment */
if ((shmaddr = shmat(shmid, NULL, 0)) == (char *) -1) {
printf("Error: Could not attach to memory segmentn");
exit(EXIT_FAILURE);
}
 
/* Write a character to the shared memory segment */
*shmaddr = 'a';
 
/* Detach the shared memory segment */
if (shmdt(shmaddr) == -1) {
printf("Error: Could not close memory segmentn");
exit(EXIT_FAILURE);
}
 
exit(EXIT_SUCCESS);
}

通过把 *shmaddr = ‘a’; 替换为 printf(“Segment: %sn”, shmaddr) ,你将会得到一个客户端程序并且能够读取共享内存段的数据。

运行 ipcs -m 将会输出服务共享内存段的信息:

anton<a href="http://www.jobbole.com/members/shell/" rel="nofollow">@shell</a>:~$ ipcs -m
 
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x0000022b 0 anton 644 64 0

共享内存段可以使用 ipcrm 命令移除。要了解更多的共享内存实现IPC,可以阅读Beej的共享内存段教程

其他实现IPC的方法有文件,信号,套接字,消息队列,管道,信号灯和消息传递。这些方法我不可能全部都深入讲解,但我觉得信号和管道的方法我需要提供一些有趣的例子。


信号

  介绍进程状态时,我们已经看了一个使用kill命令的信号示例。信号是把事件或者异常的发生通知进程的软件中断。

  每个信号都有一个整型标识,但通常使用 SIGXXX 来描述信号,例如 SIGSTOP 或者 SIGCONT 。内核使用信号来通知进程事件的发生,进程也可以使用kill()系统调用发送信号给进程。接收信号的进程可以忽略信号,被杀死,或者被挂起。可以使用信号处理器来处理信号并且在信号出现时任意处理信号。SIGKILL 这个特殊的信号不能被捕获(处理器处理),要杀死一个挂起的进程时可以使用这个信号。不要把 SIGKILL  SIGTERM 混淆了,当使用 Ctrl+C 或者 kill <PID> 杀死进程时默认会发送SIGKILL 信号。 SIGTERM 不会强制杀死进程并且它可以被捕获,使用 SIGTERM 的进程通常可以被清理。


管道

  管道用来把一个进程的输出连接到另外一个进程的输入。这是实现IPC最古老的方法之一。普通管道是单向通信的, 它有一个单向流。可以使用pipe() 创建一个管道,管道和Linux的其他对象一样,都被看成文件对象。
通其他文件一样,read()write()操作都适用于管道。

  命名管道是普通管道的增强版,它是双向通信的并且可以实现管道的多进程读写。这都是普通管道不能实现的。无论有没有进程对命名管道进行读写,它都会实际存在。命名管道在文件系统里以特殊设备文件存在。在GNU/Linux里,命名管道也被称为FIFOs(先进先出,First In First Out)。

这里有一个创建命名管道的例子:

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
 
int main(int argc, char **argv[])
{
if (mknod("myfifo", S_IFIFO|0666, 0) == -1) {
printf("Failed to mknodn");
exit(EXIT_FAILURE);
}
 
exit(EXIT_SUCCESS);
}

在运行目录里,我们会看到myfifo文件。它的信息和下面的类似:

prw-rw-r-- 1 anton anton 0 Dec 16 16:14 myfifo

  以上就是进程的基本介绍。写得越多我就越意识到进程有太多东西要讲了。从哪里开始讲进程和把不需要覆盖的知识划分出来,这是个很艰难的决定。共享内存段是我没有很好地规划好的一部分。回看进程间通信那部分是很有趣的。此外,因为有大量诸如Linux编程接口操作系统概念的好资源,使我们更容易回归概念思考。


参考

  下面的资源用来加深对这个领域知识的理解。如果你想学习关于操作系统的更多内容,一定要看看这些书,虽然书很厚但是值得你阅读。


本文由 伯乐在线 - 进林 翻译,sunbiaobiao 校稿。
英文出处:antonlindstrom


酷毙

雷人

鲜花

鸡蛋

漂亮
  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部