0
点赞
收藏
分享

微信扫一扫

雷电模拟器中控实现,直通&源码

瑾谋 2024-06-09 阅读 12
linux

目录

fork函数

1.问题 一

2.问题二

 3.问题三

fork常见用法

fork失败原因

进程退出

1.退出码

2.进程终止

进程终止常见方法:

 exit函数

_exit函数

进程等待

 1.为什么要进行进程等待

2.见一见猪跑

3.进程等待的方法

1.wait

2.waitpid


hello,my friend!今天,我们要开始学习新的内容了--->进程控制,进程控制涉及到操作系统如果管理和控制运行在计算机系统内的进程。我们将从fork函数,Linux进程退出,Linux进程等待,Linux进程替换等方面学习。那么接下来我们就开始敲黑板了!!

fork函数

话不多说,上码!!

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int num = 0;
int wer = 100;
int main()
{
    pid_t fd = fork();
    if (fd < 0)
    {
        printf("fork fail!\n");
    }
    else if (fd == 0)
    {
        while (2)
        {
            printf("我是子进程,wer:%d,&wer:%p\n", wer, &wer);
            num++;
            if (num == 10)
            {
                printf("wer数据已被修改,修改是由子进程完成的\n");
                wer=300;
            }
            sleep(1);
        }
    }
    else
    {
        while (1)
        {
            printf("我是父进程,wer:%d,&wer:%p\n", wer, &wer);
            sleep(3);
        }
    }
    return 1;
}

在Linux上浅浅运行一下:

1.问题 一

fork是操作系统创建子进程函数,函数在return返回时,已经把创建子进程该做的工作全部做完了(核心代码走就跑完了),也就是说:在return返回之前,子进程已经被创建好了,所以此时会存在父子两个进程。那么有两个返回值也就不奇怪了。

但是,是子进程先返回,还是父进程先返回,完全取决于调度器调度的顺序。

2.问题二

在现实生活中,一个爹可能有不止一个儿子,但一个儿子仅有一个爹(亲爹)。孩子想要找到父亲很简单,但是父亲想要找到儿子,得需要儿子的名字。

人亦如此,进程亦如此,所以父进程返回子进程的pid,子进程只需要返回0即可!!

 3.问题三

返回的本质就是写入,所以谁先返回,谁就先写入fd。因为进程具有独立性,所以会发生写时拷贝

(创建一块新的内存空间,对数据进行修改)。

既然有两个进程,并且两个进程的fd值不同,那么if,else if同时进行就很正常了。

fork常见用法

fork失败原因

进程退出

1.退出码

 这里返回的0在系统中我们称为进程退出时的退出码,可以用来标定我们进程退出时的结果是否正确。

我们写代码是为了完成翁某项事请,那么我们怎么知道任务完成的如何呢?就是靠进程退出码

上码:

#include<stdio.h>
int addfromto(int from,int to)
{
    int sum=0;
    for(int i=from;i<=to;i++)
    {
        sum+=i;

    }
    return sum;

}
int main()
{
    int ret=addfromto(1,100);
    if(ret==5050)
        return 0;
    else
        return 1;
}

 

失败的原因有很多种,成功的情况只有一种。人们仅关心失败的原因,不关心成功的原因。

一般,我们用0表示成功,!0表示失败 

但是,单纯的数字对计算机友好,但对人类不友好。所以,退出码要有对应的文字描述。1.可以自定义,2.使用系统中的退出码集。

系统进程退出码集

0:Success
1:Operation not permitted
2:No such file or directory
3:No such process
4:Interrupted system call
5:Input/output error
6:No such device or address
7:Argument list too long
8:Exec format error
9:Bad file descriptor
10:No child processes
11:Resource temporarily unavailable
12:Cannot allocate memory
13:Permission denied
14:Bad address
15:Block device required
16:Device or resource busy
17:File exists
18:Invalid cross-device link
19:No such device
20:Not a directory
21:Is a directory
22:Invalid argument
23:Too many open files in system
24:Too many open files
25:Inappropriate ioctl for device
26:Text file busy
27:File too large
28:No space left on device
29:Illegal seek
30:Read-only file system
31:Too many links
32:Broken pipe
33:Numerical argument out of domain
34:Numerical result out of range
35:Resource deadlock avoided
36:File name too long
37:No locks available
38:Function not implemented
39:Directory not empty
40:Too many levels of symbolic links
41:Unknown error 41
42:No message of desired type
43:Identifier removed
44:Channel number out of range
45:Level 2 not synchronized
46:Level 3 halted
47:Level 3 reset
48:Link number out of range
49:Protocol driver not attached
50:No CSI structure available
51:Level 2 halted
52:Invalid exchange
53:Invalid request descriptor
54:Exchange full
55:No anode
56:Invalid request code
57:Invalid slot
58:Unknown error 58
59:Bad font file format
60:Device not a stream
61:No data available
62:Timer expired
63:Out of streams resources
64:Machine is not on the network
65:Package not installed
66:Object is remote
67:Link has been severed
68:Advertise error
69:Srmount error
70:Communication error on send
71:Protocol error
72:Multihop attempted
73:RFS specific error
74:Bad message
75:Value too large for defined data type
76:Name not unique on network
77:File descriptor in bad state
78:Remote address changed
79:Can not access a needed shared library
80:Accessing a corrupted shared library
81:.lib section in a.out corrupted
82:Attempting to link in too many shared libraries
83:Cannot exec a shared library directly
84:Invalid or incomplete multibyte or wide character
85:Interrupted system call should be restarted
86:Streams pipe error
87:Too many users
88:Socket operation on non-socket
89:Destination address required
90:Message too long
91:Protocol wrong type for socket
92:Protocol not available
93:Protocol not supported
94:Socket type not supported
95:Operation not supported
96:Protocol family not supported
97:Address family not supported by protocol
98:Address already in use
99:Cannot assign requested address
100:Network is down
101:Network is unreachable
102:Network dropped connection on reset
103:Software caused connection abort
104:Connection reset by peer
105:No buffer space available
106:Transport endpoint is already connected
107:Transport endpoint is not connected
108:Cannot send after transport endpoint shutdown
109:Too many references: cannot splice
110:Connection timed out
111:Connection refused
112:Host is down
113:No route to host
114:Operation already in progress
115:Operation now in progress
116:Stale file handle
117:Structure needs cleaning
118:Not a XENIX named type file
119:No XENIX semaphores available
120:Is a named type file
121:Remote I/O error
122:Disk quota exceeded
123:No medium found
124:Wrong medium type
125:Operation canceled
126:Required key not available
127:Key has expired
128:Key has been revoked
129:Key was rejected by service
130:Owner died
131:State not recoverable
132:Operation not possible due to RF-kill
133:Memory page has hardware error

2.进程终止

进程退出的场景:

  • 代码运行完毕,结果正确
  • 代码运行完毕,结果不正确
  • 代码异常终止

进程终止常见方法:

 正常退出,可以在命令行中使用echo $?查询退出码

  • 从main函数中返回
  • 在任何地方调用exit
  • 在任何地址调用_exit 

异常退出

  • 使用Ctrl+Z组合键,终止进程
  • 使用kill -9 命令杀死进程 

 exit函数

头文件:stdlib.h

功能:为退出程序的函数

用法:

注意:括号内的参数都将返回给操作系统;

          return() 是返回到上一级主调函数,不一定会退出程序;

实例1

#include<stdio.h>
#include<stdlib.h>
int main()
{
    printf("hello world\n");
    exit(1);

}

_exit函数

_exit是操作系统接口

函数原型:

#include <unistd.h> 
void _exit(int status);  

用法:

实例: 

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

int main()
{
    printf("hello world\n");
    _exit(1);

}

exit_和exit的区别

代码:

#include<stdio.h>
#include<unistd.h>
int main()
{
    printf("hello world");
    sleep(1);
    _exit(1);

}

 

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main()
{
    printf("hello world");
    sleep(1);
    exit(1);

}

进程等待

 1.为什么要进行进程等待

2.见一见猪跑

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main()
{
    int cnt = 10;
    pid_t id = fork();
    if (id == 0)
    {
        while (cnt)
        {
            printf("我是子进程,pid:%d,ppif:%d\n", getpid(), getppid());
            sleep(1);
            cnt--;
        }
        exit(1);
    }
    sleep(15);
    pid_t idd = wait(nullptr);
    if (id > 0)
    {
        printf("idd:%d", id);
    }
}

运行一下:

3.进程等待的方法

1.wait

#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int*status); 

返回值:
成功返回被等待进程pid,失败返回-1参数:
输出型参数,获取子进程退出状态,不关心则可以设置成为nullptr

2.waitpid

这个系统调用接口有些复杂。

 #include <sys/wait.h>

pid_t waitpid (pid_t pid, int* statusp, int options);

我们先尝试写一下代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main()
{
    int cnt = 10;
    pid_t id = fork();
    if (id == 0)
    {
        while (cnt)
        {
            printf("我是子进程,pid:%d,ppif:%d\n", getpid(), getppid());
            sleep(1);
            cnt--;
        }
        exit(1);
    }
    int status=0;
    pid_t idd = waitpid(id,&status,0);
    if (idd > 0)
    {
        printf("idd:%d,stutus:%d\n", id,status);
    }
}

这里的status为什么是256呢?

这里就和waitpid的第二个参数有关了,我们好好分析一下:


我们先从如何使用入手:

int status=0;
// 现在调用处;定义一个int类型的整数
pid_t id=waitpid(fd,&status,0);
//然后将指针传入

这里我们根据status会取到子进程退出信号,退出码core dump等等信息。为什么一个变量可以获得这么多的信息呢?因为他是一个4字节类型,有32位比特位,所以我们分区块,获取数据。

status不能只简单的当做整型来看待,要当做位图来看(只研究status低16位),如图所示:

  1. 当进程正常终止时,终止信号为0,仅注意退出码会即可。
  2. 当程序中出现错误,如:除零错误,野指针问题。操作系统会向进程发送相关信号,来杀死进程,此时仅注意终止信号即可(因为进程没有正常退出,退出码无意义)。 

所以:上面的代码应该这样写:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main()
{
    int cnt = 2;
    pid_t id = fork();
    if (id == 0)
    {
        while (cnt)
        {
            printf("我是子进程,pid:%d,ppif:%d\n", getpid(), getppid());
            sleep(1);
            cnt--;
        }
        exit(1);
    }
    int status=0;
    pid_t idd = waitpid(id,&status,0);
    if (idd > 0)
    {
        printf("idd:%d,sig number:%d,chid exist code:%d\n", id,(status&0x7f),((status>>8)&0xff00));
    }
}

 

 写在最后:

因作者水平有限,难免会有错误,请各位批评指正!!

举报

相关推荐

0 条评论