概述
进程
什么是进程
程序的每次执行就会创建一个进程,进程就是一个正在执行的任务,同时随着程序的结束而结束。进程是分配资源的最小单位(0~3G)
进程运行的状态:ps -ajx 查询
D:不可中断的休眠态(信号) R:运行态 S:可中断的休眠态(信号)
T:停止状态 X:死亡状态 Z:僵尸态
附加状态:
<:高优先级 N:低优先级 L:在内存区锁定
s:会话组组长 l:进程中包含多线程 +:前台进程
多进程
子进程的创建是通过拷贝父进程完成的,子进程的所有资源都来自与父进程。当拷贝生成子进程后,父子进程执行的时候相互独立,执行没有先后顺序,时间片轮询
#include <head.h>
int main(int argc, const char *argv[])
{
//创建进程
pid_t pid;
//拷贝进程
pid = fork();
if(pid == -1){ //拷贝失败(子进程创建失败)
printf("fork errorn");
return -1;
}else if(pid == 0){ //子进程创建成功
while(1){
sleep(1);
printf("子进程1n");
}
}else{ //父进程
while(1){
sleep(1);
printf("父进程n");
}
}
return 0;
}
执行结果:
进程退出 exit/_exit函数
区别:
exit函数:是一个库函数,在退出进程是刷新缓存区
_exit函数:是一个系统调用,在退出时不会刷新缓存区
进程资源回收 wait/waitpid函数
wait(NULL) == waitpid(-1, NULL, 0) wait(&status) == waitpid(-1, &status, 0)
区别:
wait:其在父进程中使用,会阻塞等待子进程结束,NULL表示不关心子进程返回值
waitpid:-1 表示回收任意子进程,也可以填子进程号,表示回收指定子进程
0 表示阻塞等待,也可以填 WNOHANG 非阻塞等待
#include <head.h>
int main(int argc, const char *argv[])
{
pid_t pid1, pid2;
if((pid1 = fork()) == 0){
sleep(3);
printf("111111n");
exit(0);
printf("222222n");
}else{
if((pid2 = fork()) == 0){
sleep(1);
printf("333333n");
exit(0);
}else{
wait(NULL); //阻塞等待子进程结束
wait(NULL);
printf("444444n");
printf("555555");
_exit(0);
}
}
return 0;
}
执行结果:
多线程
线程是轻量级的进程,线程是调度的最小单位,线程不会分配内存空间,其共享当前进程的内存空间(0~3G),多线程没有多进程安全,但多线程的效率高。执行没有先后顺序,时间片轮询,线程间传参,可以直接使用全局变量
线程需要第三方库的安装:(在线安装)编译的时候加 -lpthread
sudo apt-get install manpages-posix manpages-posix-dev
多线程拷贝文件:
#include <head.h>
typedef struct{
const char* src;
const char* dest;
int start;
int length;
}file_t;
int get_length(const char* srcfile, const char* destfile){
int sfd, dfd, length;
if((sfd = open(srcfile, O_RDONLY)) == -1){
perror("open srcfile error");
return -1;
}
if((dfd = open(destfile, O_RDWR|O_TRUNC|O_CREAT,0666)) == -1){
perror("open destfile error");
return -1;
}
length = lseek(sfd, 0, SEEK_END);
close(sfd);
close(dfd);
return length;
}
int copy_file(const char* src, const char* dest, int start, int length){
int sfd, dfd, ret, count = 0;
char buf[128] = {0};
if((sfd = open(src, O_RDONLY)) == -1){
perror("open srcfile error");
return -1;
}
if((dfd = open(dest, O_RDWR)) == -1){
perror("open srcfile error");
return -1;
}
//定位源文件和目标文件的光标位置
lseek(sfd, start, SEEK_SET);
lseek(dfd, start, SEEK_SET);
while(1){
ret = read(sfd, buf, sizeof(buf));
if(ret <= 0){ //表示读取到结尾
break;
}
count += ret;
if(count >= length){ //超出读取范围
write(dfd, buf, length-(count-ret));
break;
}
write(dfd, buf, ret);
}
close(sfd);
close(dfd);
return 0;
}
void *task(void *arg){
file_t *f = (file_t*)arg;
copy_file(f->src, f->dest, f->start, f->length);
}
int main(int argc, const char *argv[])
{
pthread_t tid1, tid2;
int length = 0;
if(argc != 3){
printf("input error, try againn");
printf("usage: ./a.out filename1 filename2n");
return -1;
}
//获取源文件的长度,并创建目标文件
length = get_length(argv[1], argv[2]);
if(length < 0){
printf("file init error");
return -1;
}
file_t f[] = {
[0] = {
.src = argv[1],
.dest = argv[2],
.start = 0,
.length = length/2
},
[1] = {
.src = argv[1],
.dest = argv[2],
.start = length/2,
.length = length - (length/2)
}
};
//两个线程同时读取,tid1 读取上半部分 tid2 读取下半部分
if(pthread_create(&tid1, NULL, task, (void*)&f[0])){
perror("create thread 1 error");
return -1;
}
if(pthread_create(&tid2, NULL, task, (void*)&f[1])){
perror("create thread 2 error");
return -1;
}
//回收线程资源
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
return 0;
}
多线程函数
pthread_exit:退出当前线程(pthread_join()接收)
pthread_join:阻塞回收结合态的线程资源
pthread_cancle:一个线程向另一个线程发送结束信号
pthread_detach:将线程标记为分离态,在线程结束后资源自动回收
pthread_self:获取自己的线程ID
#include <head.h>
pthread_t tid1, tid2, ptid;
void *task1(void *arg){
//不可被取消
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
while(1){
sleep(1);
printf("线程1n");
}
printf("111111n");
}
void *task2(void *arg){
pthread_detach(pthread_self());
printf("线程2n");
sleep(5);
pthread_cancel(tid1);
pthread_cancel(ptid);
}
int main(int argc, const char *argv[])
{
//可以被取消
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
if(pthread_create(&tid1, NULL, task1, NULL)){
perror("create thread 1 error");
return -1;
}
if(pthread_create(&tid2, NULL, task2, NULL)){
perror("create thread 2 error");
return -1;
}
ptid = pthread_self();
printf("tid1 = %ld tid2 = %ldn", tid1, tid2);
while(1){
sleep(1);
printf("222222n");
}
return 0;
}
执行结果:
线程的互斥
在多线程中,如果多线程同时在访问同一个全局变量,就可能出现多个线程在获取变量值时候获取的是同一个值,此时在线程中操作这个变量就会出现不同步的效果。
互斥锁
1 >> 定义互斥锁:pthread_mutex_t mutex
2 >> 初始化互斥锁:pthread_mutex_init()
3 >> 上锁:pthread_mutex_lock()(没有获取锁,会阻塞等待)
pthread_mutex_trylock()(没有锁获取,立即返回)
4 >> 解锁:pthread_mutex_unlock()
5 >> 销毁锁:pthread_mutex_destroy()
#include <head.h>
pthread_mutex_t mutex;
int money = 10000;
void *task1(void *arg){
printf("线程1n");
while(1){
sleep(1);
pthread_mutex_lock(&mutex);
money -= 500;
if(money > 0){
printf("张三取了500,还剩<%d>n", money);
}else{
printf("没钱了,张三取钱失败n");
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
pthread_mutex_unlock(&mutex);
}
}
void *task2(void *arg){
printf("线程2n");
while(1){
sleep(1);
pthread_mutex_lock(&mutex);
money -= 1000;
if(money > 0){
printf("李四取了1000,还剩<%d>n", money);
}else{
printf("没钱了,李四取钱失败n");
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
pthread_mutex_unlock(&mutex);
}
}
int main(int argc, const char *argv[])
{
pthread_t tid1, tid2;
pthread_mutex_init(&mutex, NULL);
if(pthread_create(&tid1, NULL, task1, NULL)){
perror("create thread 1 error");
return -1;
}
if(pthread_create(&tid2, NULL, task2, NULL)){
perror("create thread 2 error");
return -1;
}
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
pthread_mutex_destroy(&mutex);
return 0;
}
执行结果:
当线程为分离态时需注意:
#include <head.h>
int money = 10000;
pthread_mutex_t mutex;
pthread_t tid1, tid2;
void *task(void *arg){
printf("1111n");
pthread_detach(pthread_self());
while(1){
sleep(1);
pthread_mutex_lock(&mutex);
money -= 100;
if(money > 0){
printf("取 100, 剩余 %dn", money);
}else{
printf("没钱了,1111n");
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
pthread_mutex_unlock(&mutex);
}
}
void *task1(void *arg){
printf("2222n");
pthread_detach(pthread_self());
while(1){
sleep(1);
pthread_mutex_lock(&mutex);
money -= 350;
if(money > 0){
printf("取 350, 剩余 %dn", money);
}else{
printf("没钱了,2222n");
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
pthread_mutex_unlock(&mutex);
}
}
int main(int argc, const char *argv[])
{
pthread_mutex_init(&mutex, NULL);
if(pthread_create(&tid1, NULL, task, NULL))
PRINT_ERR("create error");
if(pthread_create(&tid2, NULL, task1, NULL))
PRINT_ERR("create error");
printf("-------n");
while(1); //当线程设为分离态时,需注意主程序进程
pthread_mutex_destroy(&mutex);
return 0;
}
最后
以上就是自然火龙果为你收集整理的关于多进程与多进程需要注意的基础知识点进程多进程多线程的全部内容,希望文章能够帮你解决关于多进程与多进程需要注意的基础知识点进程多进程多线程所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复