1.c语言存储空间分配
主函数里面的大多在代码段
初始化的变量在数据段
函数外 未被初始化的数据是bss段 非初始化数据段
malloc申请空间在堆里面
调用函数是产生的地址在栈里面
命令行参数和环境变量在最高位
2.概念
程序是静止的概念,进程是程序的一次运行活动 就是程序跑起来 系统的中就多出一个进程
使用ps指令配合grep查看程序中是否存在某一进程 ps -aux|grep xxx 例如
ctrl + z 把程序当到后台挂起
fg 把后台程序放到前台
jobs 查看后台程序
bg 也是放到后台运行 但是在运行top可以找到
top类似于任务管理器
nice 设置进程优先级
nice 9 ./a.out
renice 改变优先级
renice 8 5678(pid号)
3.父子进程
A创建了进程B 。A就是父进程 父子进程是相对的概念 父子进程共享正文段 并不共享存储空间部分
每一个进程都有一个非负整数表示的ID 叫做pid 类似于身份证
getpid 获取进程pid ,getppid获取父进程pid
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
int main()
{
pid_t pid;
pid=getpid(); //getpid获取进程号
printf("my pid is %d\n",pid);
return 0;
}
fork()函数创建进程 返回两次 调用失败返回-1
返回值为0 代表当前进程是子进程
返回值为非负数 代表当前进程是父进程
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
pid_t pid;
printf("pid is:%d\n",getpid());
pid=fork(); //创建进程 pid为返回值
printf("touch pid\n"); //父子进程 都会执行此程序和下面的程序
//父进程执行 子进程执行fork后的程序 没有顺序相互争夺cpu
if(pid >0) //返回值大于0 是父进程
{
printf("father fid is: %d\n",getpid());
}else if(pid ==0) //返回值等于0 是子进程
{
printf("child pid is: %d\n",getpid());
}
return 0;
}
4.进程应用实例
1.只有输入1 才会创建子进程 然后子进程一直循环 等待再次输入1
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
pid_t pid;
int data;
while(1)
{
printf("please input data:\n");
scanf("%d",&data);
if(data==1){
pid=fork();
if(pid>0) //父进程
{
printf("no things\n");
}else if(pid == 0)
{ //子进程
while(1){
printf("do net request!pid=%d\n",getpid());
sleep(3);
}
}
}else{
printf("do wait a minute!\n");
}
}
return 0;
}
2.父子进程各自循环3次
vfork()函数直接使用父进程存储空间 不拷贝 使用此函数子进程会先运行 exit退出后父进程才会运行
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
pid_t pid;
int cnt =0;
pid=vfork();
//创建进程 pid为返回值,使用vfork函数 子进程会先运行 exit退出后父进程才会运行
//vfork()直接调用父进程的存储空间 不拷贝空间 子进程中改变cnt的值 父进程也会改变
if(pid >0) //返回值大于0 是父进程
{
while(1){
printf("father fid is: %d ",getpid());
printf("cnt = %d\n",cnt);
sleep(1);
cnt++;
if(cnt ==6)
{
exit(0);
}
}
}else if(pid ==0) //返回值等于0 是子进程
{
while(1){
printf("child pid is : %d cnt = %d\n",getpid(),cnt);
sleep(1);
cnt++;
if(cnt == 3)
{
exit(0);//_exit(0)跟_Exit(0) 都可以退出
}
}
}
return 0;
}
3.父进程等待子进程退出 使用wait函数 父进程会等待子进程运行完毕后在运行 子进程就会被收集
wait函数如果其还有子进程在运行 则父进程阻塞 一直等到子进程退出 获取子进程终止状态
正常退出 返回值是5
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include <sys/wait.h>
int main()
{
pid_t pid;
int cnt =0;
int status=0;
pid=fork();
if(pid >0) //返回值大于0 是父进程
{
wait(&status); //使用wait函数 父进程会等待子进程运行完毕后在运行 子进程就会被收集
printf("child quit,chile status = %d\n",WEXITSTATUS(status));
while(1){
printf("father fid is: %d ",getpid());
printf("cnt = %d\n",cnt);
cnt++;
sleep(1);
if(cnt==5)
{
exit(5);
}
}
}else if(pid ==0) //返回值等于0 是子进程
{
while(1){
printf("child pid is:%d my father pid is:%d cnt=%d\n",getpid(),getppid(),cnt);
sleep(1);
cnt++;
if(cnt == 3)
{
exit(5); //正常退出 5 异常退出 3
}
}
}
return 0;
}
5.孤儿进程
父进程如果不等待子进程退出 父进程在子进程之前就提前结束自己,此时子进程是孤儿进程
为避免过多的孤儿进程 init进程会收集孤儿进程 成为孤儿进程的父进程 pid=1