Linux编程:进程管理


本文内容:
1. 进程产生方式
2. 进程间通信和同步
3. 线程


1. 进程产生方式

产生一个进程有多种方式,如fork(), system(), exec()函数等。

1.1 fork()

简介

    #include <unistd.h>
    #include <sys/types.h>
    pid_t fork (void);

创建与当前进程几乎完全相同的子进程。
调用fork函数后,系统给新进程分配资源,例如存储数据与代码空间,然后把原来进程的所有值都复制到新进程中,只有少数的值与原进程不同。
fork()之后,子进程与父进程中的变量名相同,但不共享,子进程或父进程中改变某变量的值不会影响另一个进程中相同名称的变量值。

  • 调用失败返回小于0的值:
    errno=EAGAIN,当前的进程数已经达到系统上限。
    errno=ENOMEM,系统内存不足。
  • 调用成功返回两个值:
    pid_t=0:子进程空间
    pid_t>0:父进程空间

调用成功后,子进程和父进程都要执行fork以后的语句,通过判断fork的返回值来区分父进程和子进程。

fork()例程

#include <unistd.h>
#include <stdio.h>
int main(){
  pid_t fpid;
  int  count =0;
  fpid=fork();
  if(fpid<0)//调用失败
    printf("error in fork!");
  else if(fpid==0) {  /子进程要执行的部分
    printf("i am the child process,my pid is %d\n",getpid());
    count++;
  }
  else {  //父进程要执行的部分
    printf("i am the parent process,my pid is %d\n",getpid());
    count++:
  }
  printf("count is:%d\n",count);
  return 0;
}

执行过程:

image.png

执行结果:
i am the child process,my pid is 3
count is 1
i am the parent process ,my pid is 2
count is 1
由于这两个进程是独立的,存在于不同的地址空间,因此count变量不是共用的
参考:https://blog.csdn.net/jason314/article/details/5640969

1.2 system()

简介
system()函数调用外部shell命令在当前进程中开始另一个进程,阻塞当前进程,直到外部命令执行完毕。

#include <stdlob.h>
int system(const char command);
//command为需要执行的外部命令

执行system()函数时,会调用fork()、 execve()、 waitpid()等函数,其中任意一个调用失败将会导致system()调用失败。
返回值:

  • 失败:返回-1;
  • command不能执行:返回127;
  • 成功:返回进程状态值。

system()例程

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
  int ret;
  printf("pid:%d \n",getpid());
  ret=system("mkdir test");
  printf("ret:%d \n",ret);
  return 0;
}

执行结果:


image.png

当前进程的ID为3368,system()执行“mkdir test”命令后返回值为0.
执行结束后,当前目录下出现了新建的目录test。

1.3 exec()

简介
exec()族函数公有6个:

#include <unistd.h>
extern char **environ;
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ..., char const *envp[]);
int execve(const char *path, const char *arg[]);
int execvp(const char *path, const char *arg[]);

只有esecve()是真正的系统调用,其他都是此基础上进行包装的库函数。
exec()函数族的作用是根据指定的文件名找到可执行文件名,并在原来的进程内部执行此可执行文件。
exec()协议族调用成功不会返回,失败则会返回-1。
在Linux系统中,调用fork()之后进行exec()系统调用,系统就不会对父进程进行复制,而是直接使用exec()指定的参数覆盖原有进程,利于节省时间。

exec()族成员函数介绍

  1. execl()
    #include <unistd.h>
    int execl(
      const char *path, //要执行命令的路径
      const char *arg, //要启动程序所带的参数,一般第一个参数为要执行的命令名
      .../* (char *) NULL */ //命令参数,最后一个必须为NULL
    );

将当前的进程替换成一个新的进程,
执行到exec()函数时当前进程就会结束新进程则开始执行。但新进程保留之前进程的进程号
执行成功返回0,失败返回-1并设置errno信息
参考网站:https://www.cnblogs.com/mickole/p/3187409.html

  1. execlp()

  2. execle()

  3. execve()

  4. execvp()

2. 进程间通信和同步

消息队列
msgrcv

include <sys/types.h>
include <sys/ipc.h>
include <sys/msg.h>
int msgrcv(
  int msgid,//消息队列标识
  void *msgp,//存放消息的结构体,类型要与msgsnd函数发送的类型相同
  size_t msgsz,//接受消息的大小,不含消息类型占用的4个字节
  long msgtyp;//接受类型
  int msgflg;//接受方式
);
//调用成功返回读取到的消息长度,失败返回错误码
msgtyp的值 含义
0 接受第一个消息
>0 接受类型等于msgtyp的第一个消息
<0 接受类型等于或小于msgtyp绝对值的第一个消息
msgflg的值 含义
0 阻塞式,没有该类型的消息则一直等待
IPC_NOWAIT 如果没有满足条件的消息则立即返回,错误码为ENOMSG
IPC_EXCEPT 与msgtyp配合是,返回队列中一地个类型不为msgtyp的消息
IPC_NOERROR 如果满足条件的消息内容大于size,则把消息截断,截断部分丢弃

解除阻塞的条件有三个:
1.消息队列中有了满足条件的消息
2.msgid代表的消息队列被删除
3.调用msgrcv的进程被信号中断

错误码 含义
E2BIG 消息长度大于size,而没有设置IPC_NOERROR
EIDRM 标识为msgid的消息队列已被删除
EACCESS 没有读取权限
EFAULT msgp指向无效的内存地址
ENOMSG msgflg为IPC_NOWAIT,而队列中无消息可读
EINTR 等待读取队列的消息是被信号中断

有关消息队列的其他函数见:
https://blog.csdn.net/guoping16/article/details/6584024
waitpid

#include <sys/types.h>
#incude <sys/wait.h>
pid_t waitpid(
  pid_t pid,//进程ID
  int *status,//返回参数
  int options//调用选项
);

暂时停止目前进程的执行,直到有信号到来或子进程结束。

  • pid
    pid>0 :只等待ID等于pid的子进程
    pid=0 :等待同一个进程组中的任何子进程
    pid=-1 :等待任何一个子进程退出
    pid<-1 :等待一个指定进程组中的任何子进程退出,这个进程组的ID等于pid的绝对值

  • status
    返回子进程的结束状态和进程识别码,可以设置为NULL

  • option
    option=0:不使用此功能
    option=WNOHANG:即使没有子进程退出也会立即返回
    option=WUNTRACED:极少用
    信号
    kill

    include <sys/types.h>
    include <signal.h>
    int kill(//用于向任何进程或进程组发送信号
      pid_t pid,//进程号
      int sig//准备发送的信号代码
    );
    

参考:https://www.cnblogs.com/leeming0222/articles/3994125.html
signal

#include <signal.h>
typedef void(*sighandler_t) int
sighandler_t signal(
  int signum,//要处理的信号类型,可以取除了SIGKILL和SIGSTOP外的任何一种信号
   sighandler_t handler//与信号关联的动作
);

当进程接收到类型为signal的信号时,不管程序执行到那一部分,立即执行handler动作。执行结束后,控制权返回进程被中断的一点继续进行。
参考:https://blog.csdn.net/yockie/article/details/51729774

#include <signal.h>
int sigempty(sigset_t *set);
//初始化set指向的信号集,清除其中的所有信号
int sigfillset(sigset_t *set);
//初始化set指向的信号集,使其包含所有信号
int sigaddset(sigset_t *set, int signo);
//在信号集中添加一个信号
int sigdeleset(sigset_t *set, int signo);
//在信号集中删除一个信号
int sigismember(sigset_t *set, int signo);
//判断某信号是否存在信号集中

参考:http://blog.sina.com.cn/s/blog_6f916d330100ycnh.html

3. 线程

参考文献

  1. 《Linux网络编程(第2版)》,宋敬彬等编著。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容

  • Linux 进程管理与程序开发 进程是Linux事务管理的基本单元,所有的进程均拥有自己独立的处理环境和系统资源,...
    JamesPeng阅读 2,442评论 1 14
  • 来源:IBM译者:ljianhui链接:blog.csdn.net/ljianhui/article/detail...
    有文化_0a9b阅读 624评论 0 1
  • 进程相关概念 内核的功能 进程管理、文件系统、网络功能、内存管理、驱动程序、安全功能等。 process 进程,正...
    夹克K阅读 974评论 0 1
  • 进程 1.基本描述 进程是处于执行期的程序以及相关的资源总称。 相关的资源:打开的文件,挂起的信号,内核内部数据,...
    MagicDong阅读 480评论 0 0
  • 落日,余晖 他静静的坐在那,脸朝着快要落山的太阳, 就这样,不说话的沉默, 直到最后一丝阳光消失不见, 接着他费力...
    沉欢阅读 439评论 5 6