进程的创建以及进程间的通信

  进程是一个运行着一个或多个线程的地址空间和这些线程所需要的系统资源;通过ps -ajx命令来打印当前所有进程;其中具体状态表示为:S表示睡眠,R表示可运行,D表示等待,T表示停止,Z表示僵尸进程;PID表示进程号,PPID表示父进程号;

  一: PID ,PPID可以通过函数getpid(),getppid()获得, 下面是获取代码

 1 #include <stdio.h>
 2 #include <sys/types.h>
 3 #include <unistd.h>
 4
 5 int main()
 6 {
 7     pid_t myself_pid = getpid();
 8     pid_t parent_pid = getppid();
 9
10     printf("myself_pid is %d\n", myself_pid);
11     printf("parent_pid is %d\n", parent_pid);
12
13     return 0;
14 }

   二: 创建一个新的进程

    创建一个新的进程有三种方式:fork();system();exel ()族;

    (1)system();

      system()函数调用“/bin/sh -c command”执行特定的命令,阻塞当前的进程直到command执行完毕

      下面是通过system()执行ls -a命令

 

 1 #include <stdio.h>
 2
 3 int main()
 4 {
 5     //创建一个新进程
 6     system("ls -a");
 7     printf("Over\n");
 8
 9
10     return 0;
11 }

    (2)exel族包含成员(execl,execlp,execle,execv,exevp,execve);

      exel系列函数是替换型创建进程(子进程替换原有进程,和父进程做不同的事),只有PID保持不变(和调用exec的进程PID一样);

      其部分原型如下:

      int exelc(const char *path, const char * arg, ...);

      int execlp(const char *file, const char * arg, ...);

      int execv(const char *path, char * const argv[ ]);

      

 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include <stdlib.h>
 4
 5 int main()
 6 {
 7     int ret = 0;
 8     char *argv[3] = {"ls", "-a", NULL};
 9
10     //创建新进程
11     ret = execv("/bin/ls", argv);
12     if(ret < 0) {
13         perror("execv");
14         exit(EXIT_FAILURE);
15     }
16
17     printf("hello world\n"); //运行程序可以看到,没有输出 "hello world"(被替换)
18
19     return 0;
20 }

    (3) fork();

      一个现有进程可以调用fork()函数创建一个新的进程, 由fork创建的进程叫做子进程,fork函数调用一次但返回两次,两次返回的唯一区别是:

      子进程中返回的是0值,二父进程中返回的是子进程的PID

 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include <stdlib.h>
 4
 5 int main()
 6 {
 7     pid_t pid = 0;
 8
 9     pid = fork();
10     if(pid < 0) {
11         perror("fork");
12         exit(EXIT_FAILURE);
13     }
14
15     //子进程
16     if(pid == 0) {
17         printf("this is child pid is: %d, ppid is: %d\n", getpid(), getppid());18
19     }
20     //父进程
21     if(pid > 0) {
22         printf("this is parent pid is: %d, ppid is: %d\n", getpid(), getppid());
23     }
24
25     printf("hello world\n");//可以看到"hello world"被打印了两次(父进程,子进程)
26 }

  三:下面程序是父进程给文件加一把读锁,然后进入睡眠,子进程先睡 1秒钟,然后去验证文件锁,验证子进程看到的锁文件的进程是否是父进程

  

 1 #include <stdio.h>
 2 #include <fcntl.h>
 3 #include <stdlib.h>
 4
 5 int main()
 6 {
 7
 8     pid_t pid = fork();
 9     if(pid > 0) {
10         printf("this is father\n");
11
12         //打开文件
13         int fd = 0;
14         fd = open("txt", O_RDWR);
15         if(fd < 0) {
16             perror("open");
17             exit(EXIT_FAILURE);
18         }
19
20         int len = lseek(fd, 0, SEEK_END);//获取文件大小
21         lseek(fd, 0, SEEK_SET);
22
23         //父进程对文件加读锁
24         struct flock lock;
25         lock.l_type = F_RDLCK;
26         lock.l_whence = SEEK_SET;
27         lock.l_start = 0;
28         lock.l_len = len;
29         int ret = fcntl(fd, F_SETLK, &lock);
30         if(ret < 0) {
31             perror("child fcntl");
32             exit(EXIT_FAILURE);
33         }
34         sleep(3);
35         exit(EXIT_SUCCESS);
36     }
37
38     //子进程
39     printf("child\n");
40     sleep(1);
41     int fd = 0;
42     fd = open("txt", O_RDWR);
43     if(fd < 0) {
44         perror("open");
45         exit(EXIT_FAILURE);
46     }
47     int len = lseek(fd, 0, SEEK_END);
48     lseek(fd, 0, SEEK_SET);
49
50     //子进程尝试去加写锁
51     struct flock lock;
52     lock.l_type = F_WRLCK;
53     lock.l_whence = SEEK_SET;
54     lock.l_start = 0;
55     lock.l_len = len;
56     int ret = fcntl(fd, F_GETLK, &lock);
57     if(ret < 0) {
58         perror("parent fcntl");
59         exit(EXIT_FAILURE);
60     }
61
62
63     printf("parent is: %d\n", getppid());
64     printf("lock.l_pid is: %d\n", lock.l_pid);
65
66     if(lock.l_type == F_RDLCK) {
67         printf("read lock\n");
68     }
69     printf("lock.l_whence is: %d\n", lock.l_whence);
70     printf("lock.l_len is: %d\n", lock.l_len);
71
72     close(fd);
73     exit(EXIT_SUCCESS);
74 }

      

时间: 2024-10-13 19:47:53

进程的创建以及进程间的通信的相关文章

LINUX内核分析第六周学习总结——进程的描述和进程的创建

LINUX内核分析第六周学习总结——进程的描述和进程的创建 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.知识概要 进程的描述 进程描述符task_struct数据结构(一) 进程描述符task_struct数据结构(二) 进程的创建 进程的创建概览及fork一个进程的用户态代码 理解进程创建过程复杂代码的方法 浏览进程创建过程相关的关键代码 创建的新进程是从哪里开始执行的

linux之Deamon进程创建及其进程exit,_exit,return之间的区别

Dameon进程又被称做守护进程,一般来说他有以下2个特点: 1.生命周期非常长,一旦启动,一般不会终止,直到系统推出,不过dameon进程可以通过stop或者发送信号将其杀死 2.在后台执行,不跟任何控制终端关联,终端信号比如:SIGINT,SIGQUIT,SIGTSTP,以及关闭终端都不会影响deamon 如何编写Daemon进程,需要遵循以下规则: (1)执行fork()函数,父进程退出,子进程继续 执行这一步,原因有二: ·父进程有可能是进程组的组长(在命令行启动的情况下),从而不能够执

进程篇(3: 基本进程控制)--请参照本博客“操作系统”专栏

1. 进程标识符: 每个进程都有一个非负整型表示的唯一进程ID.但进程ID可以重用,当一个进程终止之后,其进程ID就可以再次被重用了. UNIX系统中常常有一些专用的进程: ID为0的进程通常是调度进程,常常被称为交换进程(swapper),该进程是内核的一部分,它并不执行磁盘上的任何程序,因此也被称为系统进程. ID为1的进程通常是init进程,在自举过程结束后由内核调用,在比较新的版本中是/sbin/init.此进程负责在自举内核后启动一个UNIX系统.init通常读取与系统有关的初始化文件

进程控制、孤儿进程和僵尸进程

一.进程控制 1.进程标识 1.操作系统里每打开一个进程都会创建一个进程ID,这是唯一标识进程的编号,即PID. 2.PID 在任何时刻都是唯一的,但是可以重用.当进程终止并被回收以后,其 PID 就会被系统回收 3.进程的 PID 由系统内核根据延迟重用算法生成,以确保新进程的 PID 不同于最近终止进程的 PID. 4.进程PID的最大值是有限的(因系统的不同而不同),需要及时回收 2.特殊进程 0 号进程:通常是调度进程,常常被称为交换进程(swapper).该进程是内核的一部分,所有进程

1.进程与线程之进程

进程模型: 1.一个进程是对正在运行程序的抽象. 2.计算机中多个程序的运行被排列成多个顺序进程(简称进程) 3.进程之间的快速切换称之为多道程序设计. 4.多道程序之间的切换时间是由物理计数器和各个进程的逻辑程序计数器相互作用决定的.逻辑计数器是专门用来记录物理计数器的,相当于一个变量. 5.多道程序之间的切换速度是不确定的.其实个人理解是物理计数器是确定的. 6.进程和程序之间的区别:运行了就是进程,不运行就是段程序. 7.同一进程运行两遍,算两个进程. 进程的创建 守护进程:有事的时候会被

python全栈开发day32-进程创建,进程同步,进程间的通信,进程池

一.内容总结 1.进程创建 1) Process:两种创建一个新进程的方法: 1.实例化Process,通过args=(,)元组形式传参,2创建类继承Process,类初始化的时候传参数 2) p.join(),阻塞主进程,执行完p进程后,释放 3)  守护进程 ,守护主程序代码执行完毕,p.daemon = True import time from multiprocessing import Process def func(): while True: print('is alive')

linux 进程间的通信

现在linux使用的进程间通信方式:(1)管道(pipe)和有名管道(FIFO)(2)信号(signal)(3)消息队列(4)共享内存(5)信号量(6)套接字(socket) 为何进行进程间的通信:A.数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M字节之间B.共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到.C.通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程).D.资源共享

Linux进程间的通信

一.管道 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: A. 管道是半双工的,数据只能向一个方向流动: B. 需要双工通信时,需要建立起两个管道: C. 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程): D. 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中. 匿名管道的创建:该函数创建的管道的两端处于一个进程中间,在实际应用中没有太大意义;因此,一

【进程编程】——msg进程间的消息队列通信

           [进程编程]--msg进程间的消息队列通信 消息队列就像一个链表,先进先出,就像排队打饭,先到先买!键值 用来获取消息队列的描述字,我感觉就像是一个定位标识符! 函数一     key_t ftok(char *pathname,char proj)返回的是一个键值------>创建队列之前一定要获取这个键值!proj:项目名,不为零即可 打开.创建函数二     int msgget(key_t key,int msgflg) //看见没,这里是要求键值的. key:键值