NAME
     pthreads - POSIX threads
 
DESCRIPTION
     POSIX.1 指定了一组叫做POSIX线程或Pthreads的编程接口(函数,头文件)。单个进程可以包含多个线程,所有线程执行相同的程序。这些线程共享相同的全局存储空间(数据段和堆),但每个线程有其自己的栈(自动变量)。
 
     POSIX.1 也要求共享一些其它属性(例如,进程范围内而不是每个线程的属性)
  • 进程ID
  • 父进程ID
  • 进程组ID和会话ID
  • 控制终端
  • 用户和组IDs
  • 打开的文件描述符
  • 记录锁(参考fcntl(2))
  • 信号处理
  • 文件创建掩码模式(umask(2))
  • 当前目录(chdir(2))和root目录(chroot(2))
  • 定时器(settimer(2))和POSIX定时器(timer_create(2))
  • 优先级值(setpriority(2))
  • 资源限制(setrlimit(2))
  • CPU使用时间(times(2))和资源使用情况的测量值
 
     和栈一样,POSIX.1指出,对于各个线程其它各属性是不同的,包括:
  • 线程ID(pthread_t数据类型)
  • 信号掩码(pthread_sigmask(3))
  • errno变量
  • 替换信号处理栈
  • 实时调度策略和优先级(shed_setscheduler(2)和sched_setparam(2))
 
     下面是只是Linux系统的特点,对于每个线程都不同:
  • capabilities(capabilities(7))
  • CPU affinity(sched_setaffinity(2))
     线程函数返回值
     大多数线程函数成功后返回0,失败后返回错误码。注意线程函数不会设置errno值,对每个能返回错误码的线程函数,POSIX.1指定这种函数对于错误EINTR永远也不会失败。
 
     线程ID
     在一个进程中每个线程都有唯一一个线程ID(保存在pthread_t类型中),这个ID通过调用pthread_create(3)得到,一个线程可以通过pthread_self()得到其自身线程ID,线程ID仅在进程范围内是唯一的,一个线程ID还能被重新利用,例如,在一个终止线程在被回收后,或者一个分离的线程终止后,这个线程ID可能被新的线程使用。在所有接收线程ID作为参数的线程函数中,这个ID实际指向相同调用进程中的线程。
 
     线程安全函数
     一个线程安全函数可以同时被多个线程安全地调用(例如,不管是什么都能给出相同的结果)。
     POSIX.1-2001  和 POSIX.1-2008 要求所有在标准中指定的函数是线程安全的,除了下面的函数:
           asctime()                                                    
           basename()                                                   
           catgets()                                                    
           crypt()                                                      
           ctermid() if passed a non-NULL argument                      
           ctime()                                                      
           dbm_clearerr()                                               
           dbm_close()                                                  
           dbm_delete()                                                 
           dbm_error()                                                  
           dbm_fetch()                                                  
           dbm_firstkey()                                               
           dbm_nextkey()                                                
           dbm_open()                                                   
           dbm_store()                                                  
           dirname()                                                    
           dlerror()                                                    
           drand48()                                                    
           ecvt() [POSIX.1-2001 only (function removed in POSIX.1-2008)]
           encrypt()                                                    
           endgrent()                                                   
           endpwent()                                                   
           endutxent()                                                  
           fcvt() [POSIX.1-2001 only (function removed in POSIX.1-2008)]
           ftw()                                                        
           gcvt() [POSIX.1-2001 only (function removed in POSIX.1-2008)]
           getc_unlocked()                                              
           getchar_unlocked()                                           
           getdate()                                                    
           getenv()                                                            
           getgrent()                                                          
           getgrgid()                                                          
           getgrnam()                                                          
           gethostbyaddr() [POSIX.1-2001 only (function removed in POSIX.1-2008)]
           gethostbyname() [POSIX.1-2001 only (function removed in POSIX.1-2008)]
           gethostent()                                                        
           getlogin()                                                          
           getnetbyaddr()                                                      
           getnetbyname()                                                      
           getnetent()                                                         
           getopt()                                                            
           getprotobyname()                                                    
           getprotobynumber()                                                  
           getprotoent()                                                       
           getpwent()                                                          
           getpwnam()                                                          
           getpwuid()                                                          
           getservbyname()                                                     
           getservbyport()                                                     
           getservent()                                                        
           getutxent()                                                         
           getutxid()                                                          
           getutxline()                                                        
           gmtime()                                                            
           hcreate()                                                           
           hdestroy()                                                          
           hsearch()                                                           
           inet_ntoa()                                                         
           l64a()                                                              
           lgamma()                                                            
           lgammaf()                                                           

lgammal()                               
           localeconv()                            
           localtime()                             
           lrand48()                               
           mrand48()                               
           nftw()                                  
           nl_langinfo()                           
           ptsname()                               
           putc_unlocked()                         
           putchar_unlocked()                      
           putenv()                                
           pututxline()                            
           rand()                                  
           readdir()                               
           setenv()                                
           setgrent()                              
           setkey()                                
           setpwent()                              
           setutxent()                             
           strerror()                              
           strsignal() [Added in POSIX.1-2008]     
           strtok()                                
           system() [Added in POSIX.1-2008]        
           tmpnam() if passed a non-NULL argument  
           ttyname()                               
           unsetenv()                              
           wcrtomb() if its final argument is NULL 
           wcsrtombs() if its final argument is NULL
           wcstombs()

           wctomb()                                 
 
     异步撤销安全函数
     一个异步撤销安全函数是当异步撤销能力被启用后,在应用中可以被安全地调用。
     仅仅下面的函数在POSIX.1-2001和POSIX.1-2008要求是异步线程安全的:
           pthread_cancel()       
           pthread_setcancelstate()
           pthread_setcanceltype()
 
     撤销点
     POSIX.1 指定一些确定的函数必须是撤销点,而还有一些函数可能是撤销点。如果一个线程是可以撤销的,它的撤销类型是延迟的,一个撤销请求对那个线程还是未决的,然后当它调用一个撤销点时线程被撤销。
     下面的函数POSIX.1-2001和/或POSIX.1-2008要求是撤销点:
           accept()
           aio_suspend()
           clock_nanosleep()
           close()
           connect()
           creat()
           fcntl() F_SETLKW
           fdatasync()
           fsync()
           getmsg()
           getpmsg()
           lockf() F_LOCK
           mq_receive()
           mq_send()
           mq_timedreceive()
           mq_timedsend()
           msgrcv()
           msgsnd()
           msync()
           nanosleep()
           open()
           openat() [Added in POSIX.1-2008]
           pause()
           poll()
           pread()
           pselect()
           pthread_cond_timedwait()
           pthread_cond_wait()
           pthread_join()
           pthread_testcancel()
           putmsg()
           putpmsg()
           pwrite()
           read()
           readv()
           recv()
           recvfrom()
           recvmsg()
           select()
           sem_timedwait()
           sem_wait()
           send()
           sendmsg()
           sendto()
           sigpause() [POSIX.1-2001 only (moves to "may" list in POSIX.1-2008)]
           sigsuspend()
           sigtimedwait()
           sigwait()
           sigwaitinfo()
           sleep()
           system()
           tcdrain()
           usleep() [POSIX.1-2001 only (function removed in POSIX.1-2008)]
           wait()
           waitid()
           waitpid()
           write()
           writev()
 
     下面的函数根据POSIX.1-2001和/或POSIX.1-2008或许可能是撤销点:
           access()
           asctime()
           asctime_r()
           catclose()
           catgets()
           catopen()
           chmod() [Added in POSIX.1-2008]
           chown() [Added in POSIX.1-2008]
           closedir()
           closelog()
           ctermid()
           ctime()
           ctime_r()
           dbm_close()
           dbm_delete()
           dbm_fetch()
           dbm_nextkey()
           dbm_open()
           dbm_store()
           dlclose()
           dlopen()
           dprintf() [Added in POSIX.1-2008]
           endgrent()
           endhostent()
           endnetent()
           endprotoent()
           endpwent()
           endservent()
           endutxent()
           faccessat() [Added in POSIX.1-2008]
           fchmod() [Added in POSIX.1-2008]
           fchmodat() [Added in POSIX.1-2008]
           fchown() [Added in POSIX.1-2008]
           fchownat() [Added in POSIX.1-2008]
           fclose()
           fcntl() (for any value of cmd argument)
           fflush()
           fgetc()
           fgetpos()
           fgets()
           fgetwc()
           fgetws()
           fmtmsg()
           fopen()
           fpathconf()
           fprintf()
           fputc()
           fputs()
           fputwc()
           fputws()
           fread()
           freopen()
           fscanf()
           fseek()
           fseeko()
           fsetpos()
           fstat()
           fstatat() [Added in POSIX.1-2008]
           ftell()
           ftello()
           ftw()
           futimens() [Added in POSIX.1-2008]
           fwprintf()
           fwrite()
           fwscanf()
           getaddrinfo()
           getc()
           getc_unlocked()
           getchar()
           getchar_unlocked()
           getcwd()
           getdate()
           getdelim() [Added in POSIX.1-2008]
           getgrent()
           getgrgid()
           getgrgid_r()
           getgrnam()
           getgrnam_r()
           gethostbyaddr() [SUSv3 only (function removed in POSIX.1-2008)]
           gethostbyname() [SUSv3 only (function removed in POSIX.1-2008)]
           gethostent()
           gethostid()
           gethostname()
           getline() [Added in POSIX.1-2008]
           getlogin()
           getlogin_r()
           getnameinfo()
           getnetbyaddr()
           getnetbyname()
           getnetent()
           getopt() (if opterr is nonzero)
           getprotobyname()
           getprotobynumber()
           getprotoent()
           getpwent()
           getpwnam()
           getpwnam_r()
           getpwuid()
           getpwuid_r()
           gets()
           getservbyname()
           getservbyport()
           getservent()
           getutxent()
           getutxid()
           getutxline()
           getwc()
           getwchar()
           getwd() [SUSv3 only (function removed in POSIX.1-2008)]
           glob()
           iconv_close()
           iconv_open()
           ioctl()
           link()
           linkat() [Added in POSIX.1-2008]
           lio_listio() [Added in POSIX.1-2008]
           localtime()
           localtime_r()
           lockf() [Added in POSIX.1-2008]
           lseek()
           lstat()
           mkdir() [Added in POSIX.1-2008]
           mkdirat() [Added in POSIX.1-2008]
           mkdtemp() [Added in POSIX.1-2008]
           mkfifo() [Added in POSIX.1-2008]
           mkfifoat() [Added in POSIX.1-2008]
           mknod() [Added in POSIX.1-2008]
           mknodat() [Added in POSIX.1-2008]
           mkstemp()
           mktime()
           nftw()
           opendir()
           openlog()
           pathconf()
           pclose()
           perror()
           popen()
           posix_fadvise()
           posix_fallocate()
           posix_madvise()
           posix_openpt()
           posix_spawn()
           posix_spawnp()
           posix_trace_clear()
           posix_trace_close()
           posix_trace_create()
           posix_trace_create_withlog()
           posix_trace_eventtypelist_getnext_id()
           posix_trace_eventtypelist_rewind()
           posix_trace_flush()
           posix_trace_get_attr()
           posix_trace_get_filter()
           posix_trace_get_status()
           posix_trace_getnext_event()
           posix_trace_open()
           posix_trace_rewind()
           posix_trace_set_filter()
           posix_trace_shutdown()
           posix_trace_timedgetnext_event()
           posix_typed_mem_open()
           printf()
           psiginfo() [Added in POSIX.1-2008]
           psignal() [Added in POSIX.1-2008]
           pthread_rwlock_rdlock()
           pthread_rwlock_timedrdlock()
           pthread_rwlock_timedwrlock()
           pthread_rwlock_wrlock()
           putc()
           putc_unlocked()
           putchar()
           putchar_unlocked()
           puts()
           pututxline()
           putwc()
           putwchar()
           readdir()
           readdir_r()
           readlink() [Added in POSIX.1-2008]
           readlinkat() [Added in POSIX.1-2008]
           remove()
           rename()
           renameat() [Added in POSIX.1-2008]
           rewind()
           rewinddir()
           scandir() [Added in POSIX.1-2008]
           scanf()
           seekdir()
           semop()
           setgrent()
           sethostent()
           setnetent()
           setprotoent()
           setpwent()
           setservent()
           setutxent()
           sigpause() [Added in POSIX.1-2008]
           stat()
           strerror()
           strerror_r()
           strftime()
           symlink()
           symlinkat() [Added in POSIX.1-2008]
           sync()
           syslog()
           tmpfile()
           tmpnam()
           ttyname()
           ttyname_r()
           tzset()
           ungetc()
           ungetwc()
           unlink()
           unlinkat() [Added in POSIX.1-2008]
           utime() [Added in POSIX.1-2008]
           utimensat() [Added in POSIX.1-2008]
           utimes() [Added in POSIX.1-2008]
           vdprintf() [Added in POSIX.1-2008]
           vfprintf()
           vfwprintf()
           vprintf()
           vwprintf()
           wcsftime()
           wordexp()
           wprintf()
           wscanf()
 
     具体实现或许会标记其它非标准指定的撤销函数,特别地,具体实现可能会标记出其它任何阻塞的非标准函数作为撤销点。(这包括大多数可能生成文件的函数)
 
     在Linux上编译多线程程序
     在Linux上,程序使用了Phtreads API应该使用 cc -pthread来编译。
 
     POSIX线程的Linux实现
     随着时间的推移,在GNU C库中提供两种线程的实现
  • LinuxThreads: 这是原始的Pthreads实现,从glibc 2.4以后,这种实现不再被支持。
  • NPTL: (Native POSIX Threads Library)这种实现比较新,与LinuxThreds相比,NPTL提供了与POSIX.1规范更近的一致性,当创建大量线程时也有更好的性能,NPTL从glibc 2.3.2以后都是可用的,并且需要在Linux 2.6 内核中提供的特性。
     这两种实现被称之为1:1实现,意思是每个线程映射到内核调度实体,两种实现都是通过Linux clone(2)系统调用来实现,在NPTL,线程同步原语(mutexes,线程终止等待)使用futex(2)系统调用实现。
 
     LinuxThreads
     这种实现值得注意的特性如下:
  • 除了主(初始)线程,使用pthread_create(3)创建的线程,在实现中创建了一个“管理者”线程。这个线程处理线程创建和终止。(如果这个线程被不经意地杀死后,可能会导致问题出现)
  • 在实现的内部使用了信号。在Linux 2.2以后,使用了前三个实时信号,在更旧的Linux内核中,SIGUSR1和SIGUSR2被使用,应用程序要避免使用被线程实现使用的信号。
  • 线程不共享进程IDs。(实际上,LinuxThreads线程实现为比常用进程共享更多信息的进程,但是不共享通用进程ID。)LinuxThreads(包括管理线程)在使用ps(1)是都能作为分离的进程被看到。
 
     LinuxThreads实现在很多方面偏离了POSIX.1规范,包括如下:
  • 调用getpid(2)返回每个线程的不同值。
  • 在线程中而不是主线程中调用getppid(2)返回管理线程的进程ID;在这些线程中getppid(2)的返回值应该返回与主线程中getppid(2)相同的值。
  • 当一个线程使用fork(2)创建一个子进程时,任何线程应该能能够在其子进程上wait(2)。然而,实现仅仅允许创建了子进程的那个线程执行wait(2)。
  • 当一个线程调用execve(2),所有其它线程被终止(POSIX.1要求)。然而,最终的进程使用了与与调用execve(2)线程相同的PID,应该是与主线有相同的PID。
  • 线程不共享用户和组IDs,如果应用通过使用seteuid(2)或其它类似函数改变了其相关内容,这就会对设置用户ID程序造成问题,在线程函数中会导致失败。
  • 线程不共享公用的会话ID和进程组ID。
  • 线程不共享使用fcntl(2)创建的记录锁。
  • times(2)和getrusage(2)返回的信息是每个线程级别的而不是进程级别的。
  • 线程不共享信号量撤销值(参考semop(2))。
  • 线程不共享间隔定时器。
  • 线程不共享公用优先级值。
  • POSIX.1 区分指向整个进程的信号和单个线程的信号。根据POSIX.1,一个指向进程的信号(使用kill发送)应该被进程中单个选定的线程来处理。LinuxThreads不支持指向进程进程的信号:信号只能发送给特定的线程。
  • 线程有不同的替换信号栈设置,一个新的线程的替换信号栈设置从创建了线程的线程中拷贝而来,所以线程初始时是共享替换信号栈的。(一个新的线程应该使用未定义的替换信号栈启动,如果两个线程在同一时刻处理信号使用共享的替换信号栈,不可预测的程序失败可能出现)。
     NPTL
     使用NPTL,在进程中的所有线程放在相同的线程组中;线程组中的所有成员共享相同的PID,NPTL不使用管理者线程,NPTL在内部使用前两个实时信号(参看signal(7));这些信号不能被应用程序使用。
     NPTL至少还与POSIX.1有下面的不一致:
  • 线程不共享公用的优先级值
 
     一些其它的NPTL不一致仅仅出现在老版本内核中:
  • 使用times(2)和getrusage(2)返回的信息是线程级的而不是进程范围内的(在内核2.6.9中修复)。
  • 线程不共享资源限制(在内核2.6.10中修复)。
  • 线程不共享间隔定时器(在内核2.6.12中修复)。
  • 仅仅主线程被允许使用setsid(2)来开启一个新的会话(在内核2.6.16中修复)。
  • 仅仅主线程被允许使用setpgid(2)使得一个进程成为进程组leader(在内核2.6.16中修复)。
  • 线程拥有不同的替换信号栈设置,然而,一个新线程的替换信号栈设定是从创建它的线程中拷贝而来,所以初始时共享替换信号处理栈(在内核2.6.16中修复)。
 
     注意下面的更多关于NPTL实现:
  • 如果栈大小软资源限制(查看setrlimit(2)中RLIMIT_STACK中的描述)被设置成除了unlimited之外的值,这个值定义了新线程的默认栈大小。为了生效,这个限制必须在程序运行前设置,也许可以使用ulimit -s这个shell内置的命令。
     确定线程实现
     从glibc 2.3.2以后,getconf(1)命令能被用来确定系统的线程实现,例如
     
          bash$ getconf GNU_LIBPTHREAD_VERSION
          NPTL 2.3.4
     
     其它glibc版本,一个下面的命令可以用了确定默认线程实现:
 
           bash$ $( ldd /bin/ls | grep libc.so | awk '{print $3}' ) | \
                           egrep -i 'threads|nptl'
                   Native POSIX Threads Library by Ulrich Drepper et al
 
     选择线程实现: LD_ASSUME_KERNEL
     在支持LinuxThreads和NPTL(例如,glibc 2.3.x)的系统上,LD_ASSUME_KERNEL环境变量可以被用来重写动态链接器的线程实现的默认选项,这个变量指示动态链接器用来给出其运行在特殊内核版本之上。通过指定不支持NPTL的内核版本,可以强制使用LinuxThreads。(这样做常见的原因就是就是为了运行依赖于在LinuxThreads中一些不一致的特性(不工作)应用。)例如:
 
SEE ALSO
       clone(2), futex(2), gettid(2), proc(5), futex(7), sigevent(7), signal(7), and various Pthreads manual pages, for example: pthread_attr_init(3), pthread_atfork(3), pthread_cancel(3), pthread_cleanup_push(3), pthread_cond_signal(3), pthread_cond_wait(3), pthread_create(3), pthread_detach(3), pthread_equal(3), pthread_exit(3), pthread_key_create(3), pthread_kill(3), pthread_mutex_lock(3), pthread_mutex_unlock(3), pthread_once(3), pthread_setcancelstate(3), pthread_setcanceltype(3), pthread_setspecific(3), pthread_sigmask(3), pthread_sigqueue(3), and pthread_testcancel(3)
 
COLOPHON
       This page is part of release 3.35 of the Linux man-pages project.  A description of the project, and information about reporting bugs, can be found at http://man7.org/linux/man-pages/.

[译] man 7 pthreads的更多相关文章

  1. [译林军] 译~CrossBridge 简介

    本文由 9ria 社区译林军翻译,转载请注明出处.加入译林军 :http://bbs.9ria.com/thread-286920-1-1.html CrossBridge 是  Adobe  Fla ...

  2. RxJS + Redux + React = Amazing!(译一)

    今天,我将Youtube上的<RxJS + Redux + React = Amazing!>翻译(+机译)了下来,以供国内的同学学习,英文听力好的同学可以直接看原版视频: https:/ ...

  3. Entity Framework 6 Recipes 2nd Edition 译 -> 目录 -持续更新

    因为看了<Entity Framework 6 Recipes 2nd Edition>这本书前面8章的翻译,感谢china_fucan. 从第九章开始,我是边看边译的,没有通读,加之英语 ...

  4. RxJS + Redux + React = Amazing!(译二)

    今天,我将Youtube上的<RxJS + Redux + React = Amazing!>的后半部分翻译(+机译)了下来,以供国内的同学学习,英文听力好的同学可以直接看原版视频: ht ...

  5. 「译」JUnit 5 系列:条件测试

    原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...

  6. CSharpGL(31)[译]OpenGL渲染管道那些事

    CSharpGL(31)[译]OpenGL渲染管道那些事 +BIT祝威+悄悄在此留下版了个权的信息说: 开始 自认为对OpenGL的掌握到了一个小瓶颈,现在回头细细地捋一遍OpenGL渲染管道应当是一 ...

  7. [译]基于GPU的体渲染高级技术之raycasting算法

    [译]基于GPU的体渲染高级技术之raycasting算法 PS:我决定翻译一下<Advanced Illumination Techniques for GPU-Based Volume Ra ...

  8. Entity Framework 6 Recipes 2nd Edition(9-4)译->Web API 的客户端实现修改跟踪

    9-4. Web API 的客户端实现修改跟踪 问题 我们想通过客户端更新实体类,调用基于REST的Web API 服务实现把一个对象图的插入.删除和修改等数据库操作.此外, 我们想通过EF6的Cod ...

  9. Entity Framework 6 Recipes 2nd Edition(10-1)译->非Code Frist方式返回一个实体集合

    存储过程 存储过程一直存在于任何一种关系型数据库中,如微软的SQL Server.存储过程是包含在数据库中的一些代码,通常为数据执行一些操作,它能为数据密集型计算提高性能,也能执行一些为业务逻辑. 当 ...

随机推荐

  1. HDU 5636 Shortest Path

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5636 题解: 1.暴力枚举: #include<cmath> #include<c ...

  2. C#控制台应用程序

    使用C#创建控制台应用程序的基本步骤: (1)创建项目: (2)编辑C#源代码: (3)编译运行: 例题:在控制台输出“Hello world!”. 第一步:文件→新建→项目:选择“项目类型”为Vis ...

  3. 0302思考IT行业的感想

    在看完这两篇报道IT行业的报道后,可以看出IT行业在整个就业行业中是一个十分热门的行业,而且薪酬也相对较高,企业对于各种IT人才的需求很大,意味着就业的面较宽且就业的前景比较乐观.但是随之而来的问题是 ...

  4. 2nd 燃尽图

    燃尽图(burn down chart) 在项目完成之前,对需要完成的工作所作的一种可视化表示.燃尽图主要用于向项目组成员和用户提供一个工作进展的公共视图,用以描述项目的实现状态.一般来说,常常用于形 ...

  5. Python2 读取表格类型文件

    resp = My_Request_Get(xls_url) # My_Request_Get是我自己封装的请求函数,可修改为requests请求f = ]) nrows = table._dimnr ...

  6. Django之ORM其他骚操作

    Django ORM执行原生SQL # extra # 在QuerySet的基础上继续执行子语句 # extra(self, select=None, where=None, params=None, ...

  7. BZOJ 2462 矩阵模板(二维hash)

    题意:给出一个n*m的01矩阵,以及k个a*b的01矩阵,问每个是否能匹配原来的01矩阵. 由于k个矩阵的长和宽都是一样的,所以把原矩阵的所有a*b的子矩阵给hash出来.然后依次查找是否存在即可. ...

  8. 英文报道:China challenged Australian warships in South China Sea, reports say

    学习地道新闻英语表达,以下文章来自CNN By Ben Westcott and Jamie Tarabay, CNN Updated 0830 GMT (1630 HKT) April 20, 20 ...

  9. 【转】Unable to load embedded resource from assembly 无法加载的程序集嵌入的资源

    转自:http://blog.sina.com.cn/s/blog_994678b90101f035.html 项目运用IbatisNet 今天更新项目,编译完点击运行,报错如下: [“/”应用程序中 ...

  10. WIN7 右下角音量图标不见了

    1.呼叫出  任务管理器,结束掉 explorer.exe 进程 2.新建任务,浏览,找到 C:/windows/system32/systray.exe,确定加载 3.新建任务,输入explorer ...