linux编程进程与线程基本实例

1、对比

    进程是资源分配的最小单位,线程是程序执行的最小单位

    进程拥有自己的独立地址空间,线程间共享进程的所有资源


2、进程

    需要头文件 #include #include

    2.1 进程的创建

        pid_t fork( void);

        返回值: 若成功调用一次则返回两个值,子进程返回0,父进程返回子进程ID;否则,出错返回-1

#include
#include
#include
int main()
{
        pid_t p;
        p=fork();
        if(p<0)
        {
                printf("error\n");
        }
        else if(p==0)
        {
                printf("this is child!\n");
        }
        else if(p>0)
        {
                printf("this is father!\n");
        }
        return 0;
}

    2.2 wait()和waitpid()

        pid_t wait(int *statloc);

        如果成功,wait会返回被收集的子进程的进程ID,如果调用进程没有子进程,调用就会失败,此时wait返回-1

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

        作用和wait相同,只不过可以更灵活控制pid和参数

         waitpid中pid的含义依据其具体值而变:
      pid==-1 等待任何一个子进程,此时waitpid的作用与wait相同
      pid >0   等待进程ID与pid值相同的子进程
      pid==0   等待与调用者进程组ID相同的任意子进程
      pid<-1   等待进程组ID与pid绝对值相等的任意子进程

        waitpid的option常量:

      WNOHANG   waitpid将不阻塞如果指定的pid并未结束

      WUNTRACED 如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。

    2.3 exec函数族

#include 
extern char **environ;
int execl(const char *path, const char *arg, ...);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ..., char * const envp[]);

    最后一个参数都必须为NULL     

    调用失败会返回-1   

    const char *path要写绝对路径,const char *file就不用

    例如execlp("ls","ls","-l",NULL);

    execl("/bin/ls","ls","-l",NULL);

    char *arg[] = {"ls", "-a", NULL}

    execv( "/bin/ls",arg);

    execvp( "ls",arg);

    2.4 system()函数

    #include
    int system(const char *command)
    system()函数先fork一个子进程,在这个子进程中调用/bin/sh -c来执行command指定的命令。
    例如:system("ls -l");

    2.5 给一个例子

#include
#include
#include
int main()
{
	pid_t p;
	p=fork();
	if(p<0)
	{
		perror("create fork\n");
	}
	else if(p==0)
	{
		char a[10];
		sprintf(a,"%d",getppid());
		sleep(3);
		execlp("kill","kill","-9",a,NULL);
	}
	else
	{
		while(1)
		{
			printf("this is father!\n");
			sleep(1);
		}
	}
	return 0;
}

3、线程

编译时要加上 -lpthread

需要头文件#include

    3.1 线程的创建

        int pthread_create(pthread_t *tidp,const pthread_attr_t *attr,(void*)(*start_rtn)(void*),void *arg);

        若线程创建成功,则返回0。若线程创建失败,则返回出错编号,并且*thread中的内容是未定义的。        

        第一个参数为指向线程标识符的指针。        

        第二个参数用来设置线程属性。        

        第三个参数是线程运行函数的起始地址。

        最后一个参数是运行函数的参数。  

#include
#include
#include
#include
void *thread1()
{
	printf("this is thread1\n");
}
int main()
{
	pthread_t pid;
	pthread_create(&pid,NULL,thread1,NULL);
	pthread_join(pid,NULL);
	printf("main down\n");
	return 0;
}

    3.2 pthread_join()函数

        int pthread_join(pthread_t thread, void **retval);

        等待一个线程结束,成功返回0,失败返回错误号

    3.3 例子

            3.3.1传入一个参数并返回

#include
#include
#include
#include
void *thread1(void *n)
{
	printf("this is thread1\n");
	return (void *)(n+1);	
}
int main()
{
	int a=10,b;
	pthread_t pid;
	pthread_create(&pid,NULL,thread1,(void *)a);
	pthread_join(pid,(void *)&b);
	printf("b=%d\n",b);
	return 0;
}

            3.3.2传入一个结构体并返回

#include
#include
#include
#include
struct c{
	int a;
	char *b;
};
void *thread1(void *n)
{
	struct c *temp;
	temp=(struct c *)n;
	temp->a=11;
	printf("temp->a=%d\n",temp->a);
	return (void *)temp;	
}
int main()
{
	struct c *p;
	pthread_t pid;
	p=(struct c*)malloc(sizeof(struct c));
	p->a=10;
	p->b="abc";
	printf("p->a=%d\n",p->a);
	pthread_create(&pid,NULL,thread1,(void *)p);
	pthread_join(pid,(void *)&p);
	printf("p->a=%d\n",p->a);
	return 0;
}

            3.3.3传入一个字符串并返回

#include
#include
#include
void *thread1(void *b)
{
	char *c=(char *)b;
	return (void *)c;
}
int main()
{
	pthread_t p;	
	char a[10]="abc";
	char *d;
	pthread_create(&p,NULL,thread1,(void *)a);
	pthread_join(p,(void *)&d);
	fputs(d,stdout);
	return 0;
}




你可能感兴趣的:(笔记)