进程
进程是动态的,消耗内存、cup资源。程序结束时资源就释放,即进程死亡。
进程的状态
进程有五个状态:
①就绪态:当一个进程被创建出来后,但还未获得(时间片)时,该进程就为就绪态。
②执行态:获得时间片,CPU的使用权
③睡眠态:用户调用sleep函数,usleep函数 (睡眠函数)。
④暂停态:用户发送暂停信号(kill -19 进程ID)
⑤僵尸态:进程死亡就会进入到僵尸态 (主函数调用return ,调用exit,被信号杀死…)
系统分配资源的最少单位是进程(内存空间)
子进程拿到父进程的资源有如下:
1.用户ID和组ID
2.所有的环境变量
3.进程组ID 会话ID
4.当前的工作路径
5.打开的文件描述符与文件指针
6.信号函数
7.整个内存空间
不拷贝的如下:
1.进程PID号
2.记录锁
3.暂停信号
创建一个进程
pid_t fork(void);
返回值大于0即父进程
返回值等于0即子进程
int main()
{
//创建一个子进程
pid_t pid = fork();
if(pid == 0) //子进程
{
int i=0;
for(i=0;i<3;i++)
{
printf("hello\n");
}
}
if(pid > 0) //父进程
{
//先让父亲进程睡眠
sleep(1);
printf("world\n");
}
}
获得进程的id号
pid_t getpid(void)获取当前
pid_t getppid(void) 获取父进程
等待某一进程退出
pid_t waitpid(pid_t pid,int *wstatus,int options);
arg1 等待的进程pid
arg2 退出状态
arg3 属性 (0/WNOHANG)(一直等待/等待一下)
wstatus 进程的退出状态值
WIFEXITED(wstatus) //判断是否为正常退出
WEXITSTATUS(wstatus) //获取正常退出的值 (return 的值) 不能超过8位 最大为255
WIFSIGNALED(wstatus) //被信号杀死
WTERMSIG(wstatus) //获取杀死他的信号值
WIFSTOPPED(wstatus) //被信号暂停 WSTOPSIG(wstatus)//获取暂停的值
退出进程
void exit(int status);
该函数退出时会回收资源
void _exit(int status);
该函数退出时不会回收资源
int status参数与return后的值一样(多为0??)
execl族函数
使子进程去执行别的程序
int execl(const char *path,const char *arg,NULL)
arg1 绝对路径
arg2 可执行程序的参数(int argc,char *argv[])
arg3 NULL
int execv(const char *path, const char *argv[]); //与上述功能一致,只不过这个传递的是数组指针
参数一:可执行文件的路径 (绝对路径)
参数二:传递给任务函数的参数 (字符串指针数组,注意该数组末尾必须为NULL)
int execle(const char *path, const char *arg, …, (char *) NULL, char * const envp[] */); //可以附加环境变量
自动传递主进程的环境变量给子进程使用 (带环境的,可以不用写绝对路径)
int execlp(const char *file, const char arg, …
/ (char *) NULL */);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],
char *const envp[]);
system
int system(const char *command);
该函数会自己创建一个进程去执行命令
——————————————————————————
线程
线程和进程的区别
进程:是系统分配资源的最少单位(分配虚拟内存)
线程:是系统调度的最少单位(分配时间片)
线程其实也需要资源的,那么线程的资源是从进程里面获取的,(虚拟内存有,数据段
代码段,堆,栈)那么我们线程与进程共享所有资源,除了自己的虚拟栈。
创建线程 pthread_create
等待线程 pthread_join
退出线程 pthread_exit
//全局变量
int poin = 100;
//子线程
void *func(void *arg)
{
while(1)
{
printf("func_poin=%d\n",poin++);
sleep(1);
if(poin == 105)
{
//线程退出
pthread_exit(NULL);
}
}
}
int main()
{
int a=100;
printf("main_poin=%d\n",poin);
//创建一个任务线程
pthread_t tid=0;
pthread_create(&tid,NULL,func,(void *)&a);
//设置为分离属性 自己回收资源
//pthread_detach(tid);
printf("main_poin=%d\n",poin++);
printf("等待子线程结束\n");
//pthread_join(tid,NULL); //回收线程的资源
while(1);
printf("等待子线程结束完毕!!\n");
}
线程属性设置
设置/获取线程的栈大小
void *func(void *arg)
{
printf("runing\n");
}
int main()
{
//创建一个线程
pthread_t tid=0;
pthread_attr_t attr;
bzero(&attr,sizeof(attr));
//设置栈空间的大小
int ret = pthread_attr_setstacksize(&attr,16384*4);
if(ret != 0)
{
perror("set fail\n");
exit(0);
}
//设置完毕后创建!!
pthread_create(&tid,&attr,func,NULL);
size_t size;
//获取栈的大小
pthread_attr_getstacksize(&attr,&size);
printf("size=%lu\n",size);
pthread_join(tid,NULL);
}
设置线程为分离属性,让线程自己回收自己的资源
int pthrea_detach(pthread_t thread);
使用线程注意事项:
1.主线程结束,所有的子线程都会死亡。
2.全局变量与线程中的局部变量同名则优先使用局部变量。
3.所有的线程共享全局变量,线程之间的通信只需要使用全局变量即可!!
4.当一个线程被设置为分离属性后,他就自己回收资源,pthread_join等待失效。
线程的取消与线程的取消处理函数
//全局变量
int poin = 100;
//子线程
void *func(void *arg)
{
//关闭取消请求
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
while(1)
{
printf("func_poin=%d\n",poin++);
if(poin == 110)
{
//重新开启取消请求
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
}
sleep(1);
}
}
//取消处理函数
void del(void *arg)
{
printf("已经把线程处理完毕啦!!\n");
}
int main()
{
//创建一个任务线程
pthread_t tid=0;
pthread_create(&tid,NULL,func,NULL);
pthread_cleanup_push(del,NULL); //注册线程取消处理函数
printf("等待子线程结束\n");
while(1)
{
int a=0;
scanf("%d",&a);
if(a== 886)
{
//线程取消信号
pthread_cancel(tid);
break;
}
}
pthread_cleanup_pop(0);//启动取消处理函数 自动去执行 注册好的函数
pthread_join(tid,NULL); //回收线程的资源
printf("等待子线程结束完毕!!\n");
}
线程的互斥锁
保护各个线程中的共享资源
互斥锁要定义为全局变量
//全局变量
int poin = 100; //共享资源
pthread_mutex_t mutex; //定义为全局变量,在所有线程中有效
//子线程
void *func(void *arg)
{
while(1)
{
//执行上锁操作
pthread_mutex_lock(&mutex);
//处理共享资源
printf("func_poin=%d\n",poin);
pthread_mutex_unlock(&mutex);
}
}
int main()
{
int a=100;
printf("main_poin=%d\n",poin);
//初始化线程锁
pthread_mutex_init(&mutex,NULL);
//创建一个任务线程
pthread_t tid=0;
pthread_create(&tid,NULL,func,(void *)&a);
//设置为分离属性 自己回收资源
pthread_detach(tid);
while(1)
{
//执行上锁操作
pthread_mutex_lock(&mutex);
//修改共享资源
printf("main_poin=%d\n",poin++);
pthread_mutex_unlock(&mutex);
}
}
线程的条件变量
使各个线程之间协调工作,使用时必须配合互斥锁
//全局变量
int poin = 100; //共享资源
pthread_mutex_t mutex; //定义为全局变量,在所有线程中有效
pthread_cond_t cond; //定义为全局变量,使他在所有线程中有效
//子线程
void *func(void *arg)
{
while(1)
{
//执行上锁操作
pthread_mutex_lock(&mutex);
printf("wati…………………………………………\n");
//等待主线程唤醒 设置一个条件变量
pthread_cond_wait(&cond,&mutex); //这把锁还是正在上锁的!!!!!
printf("wati………………OFF…………………\n");
//处理共享资源
printf("func_poin=%d\n",poin);
printf("mutex\n");
pthread_mutex_unlock(&mutex);
}
}
int main()
{
//初始化线程锁
pthread_mutex_init(&mutex,NULL);
//初始化条件变量
pthread_cond_init(&cond,NULL);
//创建一个任务线程
pthread_t tid=0;
pthread_create(&tid,NULL,func,NULL);
//设置为分离属性 自己回收资源
pthread_detach(tid);
while(1)
{
int a=0;
scanf("%d",&a);
if(a == 1)
{
//发送一个条件变量
pthread_cond_signal(&cond);
}
}
}