实验一 进程的建立

【实验软硬件环境】

Linux、Win11、GCC

【实验目的与内容】

​ 学会通过基本的Linux进程控制函数, 有父进程创建子进程,并实现协同工作。 创建两个进程,让子进程读取输入,父进 程等待子进程读完文件后继续执行。

【实验程序及分析】

Windows系统下

父进程代码 father.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include<stdio.h>
#include<windows.h>
int main()
{
STARTUPINFO sui; //启动信息结构体
PROCESS_INFORMATION pi; //在创建进程时相关的数据结构之一,该结构返回有关新进程及其主线程的信息。
ZeroMemory(&sui,sizeof(sui));
sui.cb = sizeof(STARTUPINFO); //将cb成员设置为信息结构体的大小
int sum = 0;
char content[100] = ""; //初始化content字符数组用来存放文件内容
if(CreateProcess("child.exe",NULL,NULL,NULL,FALSE,CREATE_NEW_CONSOLE,NULL,NULL,&sui,&pi))//创建进程
{
printf("已创建一个子进程\n");
for(int i = 1; i <= 100; i++)
{
sum = sum + i; //求1-100之和
Sleep(5); //延迟时间5ms
printf("Now, sum = %d\n",sum);
}
WaitForSingleObject(pi.hProcess,INFINITE); //一直等下去直到进程结束
FILE *fp = fopen("test.txt","r");
fread(content,sizeof(char),100,fp); //设置读取文件内容的相关参数
printf("子进程创建的文件内容如下:\n\n%s\n\n",content);
fclose(fp);
}
else{
printf("创建子进程失败\n");
}
printf("父进程结束运行");
printf("实验结束!");
system("pause");
return 0;
}
子进程代码 child.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdio.h>
#include <windows.h>

int main() {
printf("子进程开始运行...\n\n");
const char *something = "aaaaa";
FILE *fp;
if (fp = fopen("test.txt", "w+")) { //以可读写方式打开文件
printf("文件打开成功!\n\n");
fwrite(something, strlen(something), 1, fp); //将something写入文件中
fwrite("\nbbbbb", strlen("\nbbbbb"), 1, fp); //将另一句话写入文件中
printf("写入数据成功!\n\n");
fclose(fp);//关闭文件
fp = fopen("test.txt", "r"); //以只读方式打开文件
printf("当前文件中的内容如下:\n");
char ch = fgetc(fp); //取第一个字符
while (ch != EOF) { //当该字符不为文件结束标志时
putchar(ch); //输出该字符
ch = fgetc(fp); //继续从文件中获取字符
}
fclose(fp); //关闭文件
printf("\n子进程结束运行");
} else
printf("创建文件失败!\n");
printf("\n\n");
system("pause");
return 0;
}

代码分析
  1. 在父进程中创建子进程代码

    CreateProcess("child.exe",NULL,NULL,NULL,FALSE,CREATE_NEW_CONSOLE,NULL,NULL,&sui,&pi)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    BOOL CreateProcess( 
    LPCTSTR lpApplicationName,
    LPTSTR lpCommandLine,
    LPSECURITY_ATTRIBUTES lpProcessAttributes,
    LPSECURITY_ATTRIBUTES lpThreadAttributes,
    BOOL bInheritHandles,
    DWORD dwCreationFlags,
    LPVOID lpEnvironment,
    LPCTSTR lpCurrentDirectory,
    LPSTARTUPINFO lpStartupInfo,
    LPPROCESS_INFORMATION lpProcessInformation );

    lpApplicationName:子进程名,注意,应包含完整的路径名,且路径名 中出现斜杠处应多加一个反斜杠(转义字符), 如..\\EventChild\\Debug\\EventChild.exe

    lpCommandLine:命令行参数,可设为NULL。

    lpProcessAttributeslpThreadAttributes:进程、纯种的安全描述符,可设为 NULL表示默认的安全描述。

    bInheritHandles:打前进程中打开的句柄是否可以被子进程所继承。

    dwCreationFlags:表示子进程的创建状态和优化级别。本实例中设为CREATE_NEW_CONSOLE,表示为子进程创建一个新的控制台。

    lpEnvironment:子进程所使用的环境变量。设为NULL表示与当前进程使用相同 的环境变量。

    lpCurrentDirectory:子进程运行的初始目录。若为NULL表示与调用进程有相同 的目录。

    lpStartupInfo:用于设置子进程的各种属性。

    img

    LPCTSTR lpName:用于返回新进程的信息。

    img

  2. 父进程等待子进程完成

    WaitForSingleObject(pi.hProcess,INFINITE);

    1
    DWORD **WaitForSingleObject**(HANDLE hHandle,DWORD dwMilliseconds);

    hHandle:等待的事件对象的句柄。

    dwMilliseconds:等待的时间,超时则返回。若设为0,则立即返回;若设为INFINITE,则一直等待。

    返回值:失败则返回WAIT_FAILED。

    子进程结束前system("pause");父进程将会一直等待下去

    image-20220511234852274

    直到子进程的child.exe关闭,father.exe进程才会继续运行。

    image-20220511235712288

  3. 文件的IO操作

    父进程中读取操作

    1
    2
    FILE *fp = fopen("test.txt","r");
    fread(content,sizeof(char),100,fp);

    子进程中写入操作

    1
    2
    FILE *fp = fopen("test.txt", "w+")
    fwrite(something, strlen(something), 1, fp);

    C库函数fopen声明

    C 库函数 – fopen() | 菜鸟教程 (runoob.com)

    1
    FILE *fopen(const char *filename, const char *mode)
模式 描述
“r” 打开一个用于读取的文件。该文件必须存在。
“w” 创建一个用于写入的空文件。如果文件名称与已存在的文件相同,则会删除已有文件的内容,文件被视为一个新的空文件。
“a” 追加到一个文件。写操作向文件末尾追加数据。如果文件不存在,则创建文件。
“r+” 打开一个用于更新的文件,可读取也可写入。该文件必须存在。
“w+” 创建一个用于读写的空文件。
“a+” 打开一个用于读取和追加的文件。

【实验截图】

image-20220512001437573

image-20220512001452725

image-20220511234852274

image-20220511235712288

【实验心得体会】

学会了使用C语言创建子进程