system/exec/fork/pthread基本概念

1.system函数

函数头文件:

#include<stdlib.h>

函数定义:

int system(const char * string); 

函数说明:

System()会调用fork()产生子进程,由子进程调用string字符串所代表的命令,此命令执行完后随机返回调用进程。

返回值

-1 出现错误

调用成功但是没有出现子进程

>0 成功退出的子进程ID

system函数里,会fork出一个子进程,父进程使用waitpid等待子进程退出。

 

举例:

system("madplay north.mp3 &");//利用system函数调用madplay播放器播放*.mp3音乐

system("killall -9 madplay");//利用system函数调用killall命令将madplay终止掉 

system("killall -STOP madplay &");//利用system函数调用killall命令将madplay暂停

system("killall -CONT madplay &");//利用system函数调用killall命令恢复madplay的播放

 

 

2.exec函数

exec 调用成功,当前的调用进程将被覆盖,然后从新程序入口开始执行,新产生的进程和调用进程相同。并没有建立一个与调用进程并发的新进程,只是取代了原有进程。

对于exec调用成功后,没有任何数据返回。

#include <stdio.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
	pid_t child_id;
	if((child_id=fork())==0)
	{
		printf("Executing ping\n");
		execl("/bin/ping","ping","192.168.1.1",NULL);
	}
	else
	{
		printf("I am a parent \n");
		sleep(5);
		execl("/usr/bin/killall","killall","-9", "ping",NULL);
	}
	printf("--------end of execl-----\n");
	return 0;
}

3.fork进程

参数:pid_t fork(void);

返回值:一个是子进程返回0,第二个是父进程的返回值大于0.错误返回-1.

wait

功能:等待进程

参数:pid_t wait(int*status);返回值:调用成功,返回子进程的PID,发生错误返回-1。错误原因放在全局变量errno

父进程最后等待子进程结束,调用此函数。

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

waitpid()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数status返回,而子进程的进程识别码也会一快返回。如果不在意结束状态值,则参数status可以设成NULL。参数pid为欲等待的子进程识别码,其他数值意义如下:

pid<-1 等待进程组识别码为pid绝对值的任何子进程。

pid=-1 等待任何子进程,相当于wait()

pid=0 等待进程组识别码与目前进程相同的任何子进程。

pid>0 等待任何子进程识别码为pid的子进程。

例子:

waitpid(child_id,NULL,0);

 

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.

一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己

fork函数执行完毕后,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程。

在子进程中,fork函数返回0,在父进程中,fork返回新创建子进程的进程ID。我们可以通过fork返回的值来判断当前进程是子进程还是父进程。

自学参考http://www.cnblogs.com/bastard/archive/2012/08/31/2664896.html

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>            
#include <unistd.h>
int main(int argc, char const *argv[])
{
	char buf[100];
	int fd;
	int i=18,j=100;
	int status;
	pid_t child_id;
	if((fd=open("temp",O_CREAT|O_TRUNC|O_RDWR,0))==-1)
	{
		perror("open error");
		exit(1);
	}
	strcpy(buf,"hello for test!\n");
	if((child_id=fork())==0)
	{
		printf("I am a child \n");
		for(;i<20;i++)
		{
			sleep(1);
			j++;
			printf("--child :%d(%d)\n",i ,j);
			write(fd,buf,strlen(buf));			
		}
		//write(fd,buf,strlen(buf));
		close(fd);
		//exit(0);
	}
	else
	{
		printf("I am a parent \n");
		strcpy(buf,"hello for test-----!\n");
		for(;i<23;i++)
		{
			sleep(1);
			write(fd,buf,strlen(buf));
			printf("--parent :%d(%d)\n",i,j );			
		}
		
		//write(fd,buf,strlen(buf));
		close(fd);
		//exit(0);
	}
	//wait(&status);
	printf("--end--%d\n",getpid() );
	return 0;
}


1.线程pthread

线程是进程的一个实体,CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源

一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行

线程共享进程的整个地址空间,共享打开的文件,建立的socket等。线程有独立的栈以及一些寄存器,用来进行调度。堆,数据区和代码区是共享的

1.线程创建:

#include <pthread.h>

int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);

参数说明:

thread:指向pthread_create类型的指针,用于引用新创建的线程。

attr:用于设置线程的属性,一般不需要特殊的属性,所以可以简单地设置为NULL

*(*start_routine)(void *):传递新线程所要执行的函数地址。

arg:新线程所要执行的函数的参数。

调用如果成功,则返回值是0,如果失败则返回错误代码。

2.线程终止

#include <pthread.h>

void pthread_exit(void *retval);

参数说明:

retval:返回指针,指向线程向要返回的某个对象。

线程通过调用pthread_exit函数终止执行,并返回一个指向某对象的指针。注意:绝不能用它返回一个指向局部变量的指针,因为线程调用该函数后,这个局部变量就不存在了,这将引起严重的程序漏洞。

3.线程同步

#include <pthread.h>

int pthread_join(pthread_t th, void **thread_return);

参数说明:

th:等待的线程,线程通过pthread_create返回的标识符来指定。

thread_return:一个指针,指向另一个指针,而后者指向线程的返回值。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>            
#include <unistd.h>
#include <pthread.h>
char message[]="Hello world";
void *thread_function(void *arg)
{
	printf("thread_function is running:%s\n",(char *)arg );
	sleep(3);
	strcpy(message,"Bye!");
	pthread_exit("Thank you for your cpu time\n");
}


int main(int argc, char const *argv[])
{
	int res;
	pthread_t a_pthread;
	void *thread_result;

	res=pthread_create(&a_pthread,NULL,thread_function,(void *)message);
	if(res!=0)
	{
		perror("Thread creating ");
		exit(-1);
	}
	printf("waiting for thread to finish..\n");
	res=pthread_join(a_pthread,&thread_result);
	if(res!=0)
	{
		perror("Thread joid faile");
		exit(-1);
	}
	printf("Thread joined ,it return %s\n",(char *)thread_result );
	printf("Message is now %s\n",message );
	exit(0);
	return 0;
}

//-----------轮询-----------------//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>            
#include <unistd.h>
#include <pthread.h>
int  flag=1;
void *thread_function(void *arg)
{
	int count=1;
	while(count++<=20)
	{
	if(flag==2)
		{
			printf("--2--\n");
			flag=1;
		}
		else
		{
			sleep(1);
		}
	}
}


int main(int argc, char const *argv[])
{
	int res;
	pthread_t a_pthread;
	void *thread_result;
	int count=1;
	res=pthread_create(&a_pthread,NULL,thread_function,NULL);
	if(res!=0)
	{
		perror("Thread creating ");
		exit(-1);
	}
	while(count++<=20)
	{
		if(flag==1)
		{
			printf("--1--\n");
			flag=2;
		}
		else
		{
			sleep(1);
		}
	}

	printf("waiting for thread to finish..\n");
	res=pthread_join(a_pthread,&thread_result);
	if(res!=0)
	{
		perror("Thread joid faile");
		exit(-1);
	}
	printf("Thread joined ,it return %s\n",(char *)thread_result );
	exit(0);
	return 0;
}

//---------------信号量--------------------//

信号量控制

#include <semaphore.h>

int sem_wait(sem_t *sem);

int sem_post(sem_t *sem);

int sem_destory(sem_t *sem);


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>            
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
char buff[20];
int flag=0;
sem_t sem;
void *thread_function(void *arg)
{
	sem_wait(&sem);
	printf("sem get-1\n");
	while(strncmp("end",buff,3)!=0)
	{
		printf("you input is %s\n",buff );
		sem_wait(&sem);
		printf("sem get-2\n");
	}
	pthread_exit(NULL);
}


int main(int argc, char const *argv[])
{
	int res;
	pthread_t a_pthread;
	void *thread_result;
	int count=1;
	res=sem_init(&sem,0,0);
	if(res !=0)
	{
		perror("sem init");
		exit(-1);
	}
	res=pthread_create(&a_pthread,NULL,thread_function,NULL);
	if(res!=0)
	{
		perror("Thread creating ");
		exit(-1);
	}
	printf("input some string:\n");
	while(scanf("%s",buff))
	{
		sem_post(&sem);
		if(strncmp("end",buff,3)==0)
			break;
	}

	printf("waiting for thread to finish..\n");
	res=pthread_join(a_pthread,&thread_result);
	if(res!=0)
	{
		perror("Thread joid faile");
		exit(-1);
	}
	printf("Thread joined ,it return %s\n",(char *)thread_result );
	sem_destroy(&sem);
	exit(0);
	return 0;
}

//互斥锁

用互斥量进行线程同步

允许程序员锁住某个对象,使得每次只能有一个线程访问它。为了控制对关键代码的访问,必须在进入这段代码之前锁住一个互斥量,然后在完成操作之后解锁它。用于互斥量的基本函数和用于信号量的函数非常相似:

#include <pthread.h>

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t, *mutexattr);

int pthread_mutex_lock(pthread_mutex_t *mutex);

int pthread_mutex_unlock(pthread_mutex_t *mutex);

int pthread_mutex_destory(pthread_mutex_t *mutex);

参考:

http://blog.csdn.net/monkey_d_meng/article/details/5628663 


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>            
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
char buff[20];
int flag=0;
pthread_mutex_t mutex;
void *thread_function(void *arg)
{
	
	while(1)
	{
		pthread_mutex_lock(&mutex);
		printf("you input is %s\n",buff );
		pthread_mutex_unlock(&mutex);
		if(strncmp("end",buff,3)==0)
			break;
		sleep(1);
	}
	pthread_exit(NULL);
}


int main(int argc, char const *argv[])
{
	int res;
	pthread_t a_pthread;
	void *thread_result;
	int count=1;
	res=pthread_mutex_init(&mutex,NULL);
	if(res !=0)
	{
		perror("mutex init");
		exit(-1);
	}
	res=pthread_create(&a_pthread,NULL,thread_function,NULL);
	if(res!=0)
	{
		perror("Thread creating ");
		exit(-1);
	}
	printf("input some string:\n");
	while(1)
	{
		pthread_mutex_lock(&mutex);
		scanf("%s",buff );
		pthread_mutex_unlock(&mutex);
		if(strncmp("end",buff,3)==0)
			break;
		sleep(1);
	}
	
	printf("waiting for thread to finish..\n");
	res=pthread_join(a_pthread,&thread_result);
	if(res!=0)
	{
		perror("Thread joid faile");
		exit(-1);
	}
	printf("Thread joined ,it return %s\n",(char *)thread_result );
	pthread_mutex_destroy(&mutex);
	exit(0);
	return 0;
}

5.进程线程的差别

进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

1) 简而言之,一个程序至少有一个进程,一个进程至少有一个线程.

2) 线程的划分尺度小于进程,使得多线程程序的并发性高。

3) 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。

4) 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

5) 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值