(1)当执行程序时,main函数是的如何调用的
main函数原型是
int main(int argc,char *argv[]);
argc是命令行参数,argv是指向参数的各个指针的数组。
#include"apue.h"
int main()
{
int i;
for(i=0;i<argc;i++)
{
printf("argv[%d]:%s\n",i,argv[i]);
exit(0);
}
//编译运行后如下:
zsj@zsj-virtual-machine:~/ccode$ cc -o 7-3 7-3.c
zsj@zsj-virtual-machine:~/ccode$ ./7-3 arg1 TEST foo
argv[0]:./7-3 //第一个指针指向文件
argv[1]:arg1
argv[2]:TEST
argv[3]:foo
内核执行c程序时(使用exec函数)调用main之前先调用一个特殊例程。例程从内核取得命令行参数 和环境变量值。
(2)各种不同的进程终止方式
#include<stdlib.h>
void exit(int status);
void_Exit(int status);
#include<unistd.h>
void _exit(int status);
这三个函数都可以用来正常终止一个程序:_exit 和_Exit立即进入内核,exit则执行一些清理操作(调用执行各终止处理程序,关闭所有标准I/O流)
三个函数都带一个整型参数称为终止状态。
(a)调用这些函数时不带终止状态.
(b)main执行了一个无返回值的return语句
(c)main没有声明返回值是整型的。
以上三种情况 终止状态是未定义的。
(3)c程序的存储空间布局
text:正文段。这是由cpu执行的机器指令部分,正文段是可共享的,正文段常常是只读的。
初始化数据段。出现在任何函数以外的声明。
非初始化数据段。开始执行程序之前内核将此段中的数据初始化为0或空指针。
栈:自动变量以及每次函数调用时所保存的信息都放在栈中。递归函数每次调用自身都使用一个新的栈帧
堆:通常在堆中进行动态存储分配。
(4)如何分配存储空间
#include<stdlib.h>
void *malloc(size_t size);
void *calloc(size_t nobj,size_t size);//为指定数量具有指定长度的对象分配存储空间。
void *realloc(void *ptr,size_t newsize);
void free(*ptr);
三个函数返回值,若成功则返回非空指针,出错则返回null
(5)创建进程以及进程属性
进程标识符
每个进程都有一个非负整数表示的唯一进程ID。进程ID可以重用,当一个进程终止时,进程ID就可以重新使用了。
系统中有一些专用的进程 ID为0的表示 调度进程,被称为交换进程。并不执行磁盘上的任何程序。
ID为1的是init进程,它通常读与系统初始化有关的文件。
fork函数
#include<unistd.h>
pid_t fork(void)
返回值:子进程中返回0,父进程中返回子进程ID,出错返回-1
由fork创建的新进程称为子进程。fork函数被调用一次,但返回两次。
父进程返回新进程ID,新进程返回0。
子进程和父进程继续执行fork()之后的指令。子进程是父进程的副本。获得父进程的数据空间、堆栈、父子进程并不共享这些存储部分。父子进程共享正文段。
#include<stdio.h>
#include"apue.h"
#include<myerror.h>
int glob=6;
char buf[]="a write to stdout\n";
int main(void)
{
int var;
pid_t pid;
var=88;
if(write(STDOUT_FILENO,buf,sizeof(buf)-1)!=sizeof(buf)-1)
err_sys("write error");
printf("before fork\n");
if(pid=fork()<0)
{
err_sys("fork error");
}
else if(pid==0)
{
glob++;
var++;
}
else{
sleep(2);
}
printf("pid= %d,glob=%d,var=%d\n",getpid(),glob,var);
exit(0);
}
zsj@zsj-virtual-machine:~/ccode$ cc 8-1.c
zsj@zsj-virtual-machine:~/ccode$ ./a.out
a write to stdout
before fork
pid=14828,glob=7,var=89 //子进程的变量变了
pid=14827,glob=6,var=88 //父进程得变量值没变
zsj@zsj-virtual-machine:~/ccode$ ./a.out >temp.out
zsj@zsj-virtual-machine:~/ccode$ cat temp.out
a write to stdout
before fork
pid=14830,var=89
before fork
pid=14829,var=88
zsj@zsj-virtual-machine:~/ccode$